From 47e6770910f0537c8c6619de664077e28851228e Mon Sep 17 00:00:00 2001 From: imbajin Date: Thu, 1 Oct 2026 11:16:30 +0800 Subject: [PATCH 01/11] refactor: consolidate shared graph foundations - make struct the canonical ID, schema, query, element and codec owner - move schema network lifecycle to Store and JWT/RPC contracts to common - preserve historical formats and repair bounded HStore OLAP operations - migrate callers and add compatibility fixtures and package boundary guards - document Java migration and refresh dependency inventory and licensing --- .github/workflows/check-dependencies.yml | 16 +- README.md | 3 + docs/CONTRIBUTING.md | 15 + docs/shared-foundation-migration.md | 254 ++++ hugegraph-commons/hugegraph-common/pom.xml | 23 + .../apache/hugegraph/auth/AuthConstant.java | 2 + .../apache/hugegraph/auth/TokenGenerator.java | 31 +- .../rpc/RpcServiceConfig4Client.java | 0 .../rpc/RpcServiceConfig4Server.java | 0 .../apache/hugegraph/unit/UnitTestSuite.java | 2 + .../unit/auth/TokenGeneratorTest.java | 100 ++ hugegraph-pd/hg-pd-service/pom.xml | 20 +- .../java/org/apache/hugegraph/api/API.java | 2 +- .../apache/hugegraph/api/auth/AccessAPI.java | 2 +- .../apache/hugegraph/api/auth/BelongAPI.java | 2 +- .../api/auth/GraphSpaceGroupAPI.java | 2 +- .../apache/hugegraph/api/auth/GroupAPI.java | 2 +- .../apache/hugegraph/api/auth/ProjectAPI.java | 2 +- .../apache/hugegraph/api/auth/UserAPI.java | 4 +- .../hugegraph/api/cypher/CypherClient.java | 2 +- .../hugegraph/api/filter/ExceptionFilter.java | 2 +- .../apache/hugegraph/api/graph/BatchAPI.java | 2 +- .../apache/hugegraph/api/graph/EdgeAPI.java | 12 +- .../apache/hugegraph/api/graph/VertexAPI.java | 10 +- .../hugegraph/api/job/AlgorithmAPI.java | 2 +- .../apache/hugegraph/api/job/ComputerAPI.java | 2 +- .../apache/hugegraph/api/job/GremlinAPI.java | 4 +- .../apache/hugegraph/api/job/RebuildAPI.java | 2 +- .../org/apache/hugegraph/api/job/TaskAPI.java | 4 +- .../hugegraph/api/profile/GraphsAPI.java | 2 +- .../apache/hugegraph/api/raft/RaftAPI.java | 4 +- .../hugegraph/api/schema/EdgeLabelAPI.java | 6 +- .../hugegraph/api/schema/IndexLabelAPI.java | 8 +- .../hugegraph/api/schema/PropertyKeyAPI.java | 10 +- .../hugegraph/api/schema/VertexLabelAPI.java | 6 +- .../api/space/SchemaTemplateAPI.java | 2 +- .../api/traversers/AdamicAdarAPI.java | 6 +- .../api/traversers/AllShortestPathsAPI.java | 6 +- .../hugegraph/api/traversers/CountAPI.java | 2 +- .../api/traversers/CrosspointsAPI.java | 6 +- .../traversers/CustomizedCrosspointsAPI.java | 2 +- .../api/traversers/CustomizedPathsAPI.java | 2 +- .../api/traversers/EdgeExistenceAPI.java | 2 +- .../hugegraph/api/traversers/EdgesAPI.java | 6 +- .../api/traversers/FusiformSimilarityAPI.java | 2 +- .../api/traversers/JaccardSimilarityAPI.java | 6 +- .../api/traversers/KneighborAPI.java | 6 +- .../hugegraph/api/traversers/KoutAPI.java | 6 +- .../traversers/MultiNodeShortestPathAPI.java | 2 +- .../api/traversers/NeighborRankAPI.java | 2 +- .../hugegraph/api/traversers/PathsAPI.java | 6 +- .../api/traversers/PersonalRankAPI.java | 2 +- .../hugegraph/api/traversers/RaysAPI.java | 6 +- .../api/traversers/ResourceAllocationAPI.java | 6 +- .../hugegraph/api/traversers/RingsAPI.java | 6 +- .../api/traversers/SameNeighborsAPI.java | 8 +- .../api/traversers/ShortestPathAPI.java | 6 +- .../SingleSourceShortestPathAPI.java | 6 +- .../api/traversers/TemplatePathsAPI.java | 2 +- .../hugegraph/api/traversers/Vertices.java | 6 +- .../hugegraph/api/traversers/VerticesAPI.java | 6 +- .../traversers/WeightedShortestPathAPI.java | 6 +- .../hugegraph/auth/ContextGremlinServer.java | 2 +- .../hugegraph/auth/HugeAuthenticator.java | 14 +- .../hugegraph/auth/HugeFactoryAuthProxy.java | 4 +- .../hugegraph/auth/HugeGraphAuthProxy.java | 29 +- .../apache/hugegraph/core/GraphManager.java | 4 +- .../apache/hugegraph/kvstore/KvStoreImpl.java | 4 +- .../hugegraph/serializer/JsonSerializer.java | 14 +- .../hugegraph/serializer/Serializer.java | 12 +- .../hugegraph/server/ApplicationConfig.java | 2 +- hugegraph-server/hugegraph-core/pom.xml | 61 +- .../org/apache/hugegraph/HugeException.java | 62 - .../org/apache/hugegraph/HugeFactory.java | 2 + .../java/org/apache/hugegraph/HugeGraph.java | 39 +- .../apache/hugegraph/StandardHugeGraph.java | 26 +- .../apache/hugegraph/analyzer/Analyzer.java | 25 - .../hugegraph/analyzer/AnalyzerFactory.java | 98 -- .../hugegraph/analyzer/AnsjAnalyzer.java | 85 -- .../hugegraph/analyzer/HanLPAnalyzer.java | 105 -- .../apache/hugegraph/analyzer/IKAnalyzer.java | 69 -- .../hugegraph/analyzer/JcsegAnalyzer.java | 80 -- .../hugegraph/analyzer/JiebaAnalyzer.java | 61 - .../hugegraph/analyzer/MMSeg4JAnalyzer.java | 90 -- .../hugegraph/analyzer/SmartCNAnalyzer.java | 59 - .../apache/hugegraph/auth/AuthManager.java | 2 +- .../apache/hugegraph/auth/EntityManager.java | 12 +- .../org/apache/hugegraph/auth/HugeAccess.java | 6 +- .../org/apache/hugegraph/auth/HugeBelong.java | 6 +- .../org/apache/hugegraph/auth/HugeGroup.java | 6 +- .../apache/hugegraph/auth/HugeProject.java | 6 +- .../apache/hugegraph/auth/HugeResource.java | 22 +- .../org/apache/hugegraph/auth/HugeRole.java | 6 +- .../org/apache/hugegraph/auth/HugeTarget.java | 8 +- .../org/apache/hugegraph/auth/HugeUser.java | 6 +- .../hugegraph/auth/RelationshipManager.java | 14 +- .../apache/hugegraph/auth/ResourceObject.java | 8 +- .../apache/hugegraph/auth/SchemaDefine.java | 16 +- .../hugegraph/auth/StandardAuthManager.java | 8 +- .../hugegraph/auth/StandardAuthManagerV2.java | 8 +- .../apache/hugegraph/auth/UserWithRole.java | 2 +- .../hugegraph/backend/BackendException.java | 52 - .../hugegraph/backend/LocalCounter.java | 4 +- .../apache/hugegraph/backend/Transaction.java | 2 + .../hugegraph/backend/cache/CacheManager.java | 2 +- .../backend/cache/CacheNotifier.java | 2 +- .../backend/cache/CachedBackendStore.java | 6 +- .../backend/cache/CachedGraphTransaction.java | 8 +- .../cache/CachedSchemaTransaction.java | 6 +- .../cache/CachedSchemaTransactionV2.java | 6 +- .../hugegraph/backend/cache/LevelCache.java | 2 +- .../hugegraph/backend/cache/OffheapCache.java | 8 +- .../hugegraph/backend/cache/RamCache.java | 2 +- .../apache/hugegraph/backend/id/EdgeId.java | 325 ------ .../org/apache/hugegraph/backend/id/Id.java | 85 -- .../hugegraph/backend/id/IdGenerator.java | 471 -------- .../apache/hugegraph/backend/id/IdUtil.java | 147 --- .../backend/id/SnowflakeIdGenerator.java | 8 +- .../backend/id/SplicingIdGenerator.java | 138 --- .../hugegraph/backend/page/IdHolder.java | 6 +- .../backend/page/PageEntryIterator.java | 2 +- .../hugegraph/backend/page/PageIds.java | 2 +- .../hugegraph/backend/page/PageInfo.java | 4 +- .../hugegraph/backend/page/PageState.java | 4 +- .../hugegraph/backend/page/QueryList.java | 10 +- .../backend/page/SortByCountIdHolderList.java | 4 +- .../hugegraph/backend/query/Aggregate.java | 107 -- .../hugegraph/backend/query/Condition.java | 917 --------------- .../backend/query/ConditionQuery.java | 971 ---------------- .../backend/query/ConditionQueryFlatten.java | 9 +- .../backend/query/EdgesQueryIterator.java | 4 +- .../hugegraph/backend/query/IdQuery.java | 191 --- .../apache/hugegraph/backend/query/Query.java | 655 ----------- .../hugegraph/backend/query/QueryBatch.java | 5 +- .../backend/query/QueryResultContext.java | 9 +- .../hugegraph/backend/query/QueryResults.java | 10 +- .../serializer/AbstractSerializerAdapter.java | 66 -- .../query/serializer/QueryAdapter.java | 148 --- .../query/serializer/QueryIdAdapter.java | 46 - .../serializer/AbstractSerializer.java | 10 +- .../serializer/BinaryBackendEntry.java | 84 +- .../serializer/BinaryEntryIterator.java | 2 +- .../serializer/BinaryScatterSerializer.java | 10 +- .../backend/serializer/BinarySerializer.java | 274 ++--- .../backend/serializer/BytesBuffer.java | 1030 ----------------- .../backend/serializer/GraphSerializer.java | 12 +- .../backend/serializer/SchemaSerializer.java | 8 +- .../backend/serializer/SerializerFactory.java | 2 +- .../backend/serializer/TableBackendEntry.java | 9 +- .../backend/serializer/TableSerializer.java | 38 +- .../backend/serializer/TableSerializerV2.java | 10 +- .../backend/serializer/TextBackendEntry.java | 5 +- .../backend/serializer/TextSerializer.java | 44 +- .../backend/store/AbstractBackendStore.java | 6 +- .../store/AbstractBackendStoreProvider.java | 2 +- .../hugegraph/backend/store/BackendEntry.java | 48 +- .../backend/store/BackendEntryIterator.java | 4 +- .../backend/store/BackendMutation.java | 4 +- .../backend/store/BackendProviderFactory.java | 2 +- .../hugegraph/backend/store/BackendStore.java | 6 +- .../hugegraph/backend/store/BackendTable.java | 7 +- .../apache/hugegraph/backend/store/Shard.java | 69 -- .../backend/store/SystemSchemaStore.java | 4 +- .../backend/store/memory/InMemoryDBStore.java | 6 +- .../backend/store/memory/InMemoryDBTable.java | 20 +- .../store/memory/InMemoryDBTables.java | 32 +- .../backend/store/raft/RaftBackendStore.java | 4 +- .../store/raft/RaftBackendStoreProvider.java | 2 +- .../backend/store/raft/RaftClosure.java | 2 +- .../backend/store/raft/RaftContext.java | 6 +- .../backend/store/raft/RaftException.java | 2 +- .../store/raft/RaftGroupManagerImpl.java | 2 +- .../backend/store/raft/RaftNode.java | 2 +- .../backend/store/raft/StoreCommand.java | 2 +- .../backend/store/raft/StoreSerializer.java | 8 +- .../backend/store/raft/StoreStateMachine.java | 4 +- .../backend/store/raft/rpc/RpcForwarder.java | 2 +- .../backend/store/ram/IntIntMap.java | 2 +- .../backend/store/ram/IntLongMap.java | 2 +- .../hugegraph/backend/store/ram/RamTable.java | 16 +- .../backend/tx/AbstractTransaction.java | 12 +- .../backend/tx/GraphIndexTransaction.java | 359 ++---- .../backend/tx/GraphTransaction.java | 48 +- .../backend/tx/ISchemaTransaction.java | 14 +- .../hugegraph/backend/tx/IdCounter.java | 16 +- .../backend/tx/IndexableTransaction.java | 2 +- .../backend/tx/SchemaIndexTransaction.java | 16 +- .../backend/tx/SchemaTransaction.java | 24 +- .../backend/tx/SchemaTransactionV2.java | 18 +- .../apache/hugegraph/config/CoreOptions.java | 6 +- .../exception/ConnectionException.java | 2 +- .../exception/ErrorCodeProvider.java | 27 - .../hugegraph/exception/ExistedException.java | 2 +- .../hugegraph/exception/NoIndexException.java | 2 +- .../exception/NotAllowException.java | 33 - .../exception/NotSupportException.java | 34 - .../io/GraphSONSchemaSerializer.java | 18 +- .../hugegraph/io/HugeGraphSONModule.java | 24 +- ...ugeGraphTypeSerializerRegistryBuilder.java | 14 +- .../apache/hugegraph/io/HugeGryoModule.java | 16 +- .../hugegraph/job/EphemeralJobBuilder.java | 4 +- .../org/apache/hugegraph/job/GremlinJob.java | 2 +- .../org/apache/hugegraph/job/JobBuilder.java | 2 +- .../job/algorithm/AbstractAlgorithm.java | 8 +- .../hugegraph/job/algorithm/BfsTraverser.java | 2 +- .../hugegraph/job/algorithm/Consumers.java | 2 +- .../job/algorithm/SubgraphStatAlgorithm.java | 2 +- .../algorithm/cent/AbstractCentAlgorithm.java | 6 +- .../cent/BetweennessCentralityAlgorithm.java | 4 +- .../BetweennessCentralityAlgorithmV2.java | 4 +- .../cent/ClosenessCentralityAlgorithmV2.java | 4 +- .../cent/DegreeCentralityAlgorithm.java | 2 +- .../cent/StressCentralityAlgorithmV2.java | 4 +- .../job/algorithm/comm/KCoreAlgorithm.java | 2 +- .../job/algorithm/comm/LouvainTraverser.java | 8 +- .../job/algorithm/comm/LpaAlgorithm.java | 4 +- .../comm/TriangleCountAlgorithm.java | 4 +- .../comm/WeakConnectedComponent.java | 4 +- .../algorithm/path/RingsDetectAlgorithm.java | 2 +- .../job/algorithm/rank/PageRankAlgorithm.java | 4 +- .../job/computer/AbstractComputer.java | 2 +- .../job/schema/EdgeLabelRemoveJob.java | 4 +- .../job/schema/IndexLabelRebuildJob.java | 12 +- .../job/schema/IndexLabelRemoveJob.java | 4 +- .../job/schema/OlapPropertyKeyClearJob.java | 4 +- .../job/schema/OlapPropertyKeyCreateJob.java | 2 +- .../job/schema/OlapPropertyKeyRemoveJob.java | 4 +- .../hugegraph/job/schema/SchemaJob.java | 6 +- .../job/schema/VertexLabelRemoveJob.java | 8 +- .../job/system/DeleteExpiredIndexJob.java | 12 +- .../job/system/DeleteExpiredJob.java | 4 +- .../hugegraph/job/system/JobCounters.java | 12 +- .../org/apache/hugegraph/k8s/K8sDriver.java | 2 +- .../org/apache/hugegraph/k8s/K8sManager.java | 2 +- .../org/apache/hugegraph/k8s/K8sRegister.java | 2 +- .../org/apache/hugegraph/kvstore/KvStore.java | 2 +- .../masterelection/GlobalMasterInfo.java | 4 +- .../memory/consumer/factory/IdFactory.java | 18 +- .../consumer/factory/PropertyFactory.java | 2 +- .../consumer/impl/id/BinaryIdOffHeap.java | 10 +- .../consumer/impl/id/EdgeIdOffHeap.java | 26 +- .../consumer/impl/id/LongIdOffHeap.java | 6 +- .../consumer/impl/id/ObjectIdOffHeap.java | 2 +- .../consumer/impl/id/QueryIdOffHeap.java | 4 +- .../consumer/impl/id/StringIdOffHeap.java | 6 +- .../consumer/impl/id/UuidIdOffHeap.java | 8 +- .../property/HugeEdgePropertyOffHeap.java | 12 +- .../property/HugeVertexPropertyOffHeap.java | 12 +- .../memory/util/OffHeapMemoryUtil.java | 20 +- .../memory/util/OutOfMemoryException.java | 2 +- .../apache/hugegraph/meta/EtcdMetaDriver.java | 2 +- .../apache/hugegraph/meta/MetaManager.java | 12 +- .../apache/hugegraph/meta/PdMetaDriver.java | 2 +- .../meta/lock/PdDistributedLock.java | 2 +- .../meta/managers/AbstractMetaManager.java | 4 +- .../meta/managers/AuthMetaManager.java | 4 +- .../meta/managers/SchemaMetaManager.java | 12 +- .../managers/SchemaTemplateMetaManager.java | 2 +- .../plugin/HugeGraphGremlinPlugin.java | 2 +- .../rpc/RpcServiceConfig4Client.java | 35 - .../rpc/RpcServiceConfig4Server.java | 30 - .../apache/hugegraph/schema/EdgeLabel.java | 445 ------- .../apache/hugegraph/schema/IndexLabel.java | 359 ------ .../apache/hugegraph/schema/PropertyKey.java | 514 -------- .../hugegraph/schema/SchemaElement.java | 262 ----- .../apache/hugegraph/schema/SchemaLabel.java | 188 --- .../hugegraph/schema/SchemaManager.java | 5 + .../org/apache/hugegraph/schema/Userdata.java | 110 -- .../apache/hugegraph/schema/VertexLabel.java | 247 ---- .../schema/builder/AbstractBuilder.java | 14 +- .../schema/builder/EdgeLabelBuilder.java | 54 +- .../schema/builder/IndexLabelBuilder.java | 18 +- .../schema/builder/PropertyKeyBuilder.java | 12 +- .../schema/builder/SchemaBuilder.java | 40 - .../schema/builder/VertexLabelBuilder.java | 38 +- .../apache/hugegraph/space/GraphSpace.java | 2 +- .../apache/hugegraph/structure/GraphType.java | 25 - .../apache/hugegraph/structure/HugeEdge.java | 276 ++--- .../hugegraph/structure/HugeEdgeProperty.java | 10 +- .../hugegraph/structure/HugeElement.java | 293 ++--- .../hugegraph/structure/HugeFeatures.java | 2 +- .../apache/hugegraph/structure/HugeIndex.java | 301 ----- .../hugegraph/structure/HugeProperty.java | 27 +- .../hugegraph/structure/HugeVertex.java | 282 ++--- .../structure/HugeVertexProperty.java | 8 +- .../task/DistributedTaskScheduler.java | 4 +- .../hugegraph/task/EphemeralJobQueue.java | 2 +- .../org/apache/hugegraph/task/HugeTask.java | 19 +- .../apache/hugegraph/task/HugeTaskResult.java | 2 +- .../hugegraph/task/ServerInfoManager.java | 4 +- .../hugegraph/task/StandardTaskScheduler.java | 12 +- .../task/TaskAndResultScheduler.java | 10 +- .../task/TaskAndResultTransaction.java | 6 +- .../apache/hugegraph/task/TaskCallable.java | 2 +- .../apache/hugegraph/task/TaskManager.java | 2 +- .../apache/hugegraph/task/TaskScheduler.java | 2 +- .../hugegraph/task/TaskTransaction.java | 12 +- .../algorithm/CollectionPathsTraverser.java | 2 +- .../traversal/algorithm/CountTraverser.java | 2 +- .../algorithm/CustomizePathsTraverser.java | 2 +- .../CustomizedCrosspointsTraverser.java | 2 +- .../algorithm/EdgeExistenceTraverser.java | 6 +- .../FusiformSimilarityTraverser.java | 4 +- .../traversal/algorithm/HugeTraverser.java | 20 +- .../algorithm/JaccardSimilarTraverser.java | 4 +- .../algorithm/KneighborTraverser.java | 4 +- .../traversal/algorithm/KoutTraverser.java | 8 +- .../MultiNodeShortestPathTraverser.java | 2 +- .../algorithm/NeighborRankTraverser.java | 2 +- .../traversal/algorithm/OltpTraverser.java | 4 +- .../traversal/algorithm/PathTraverser.java | 2 +- .../traversal/algorithm/PathsTraverser.java | 2 +- .../algorithm/PersonalRankTraverser.java | 6 +- .../algorithm/PredictionTraverser.java | 2 +- .../algorithm/SameNeighborTraverser.java | 2 +- .../algorithm/ShortestPathTraverser.java | 2 +- .../SingleSourceShortestPathTraverser.java | 2 +- .../algorithm/SubGraphTraverser.java | 2 +- .../algorithm/TemplatePathsTraverser.java | 2 +- .../algorithm/iterator/NestedIterator.java | 2 +- .../algorithm/records/AbstractRecords.java | 4 +- .../records/DoubleWayMultiPathsRecords.java | 2 +- .../algorithm/records/KneighborRecords.java | 2 +- .../algorithm/records/KoutRecords.java | 2 +- .../algorithm/records/PathsRecords.java | 2 +- .../traversal/algorithm/records/Records.java | 2 +- .../records/ShortestPathRecords.java | 2 +- .../records/SingleWayMultiPathsRecords.java | 4 +- .../traversal/algorithm/steps/EdgeStep.java | 4 +- .../traversal/algorithm/steps/Steps.java | 6 +- .../algorithm/steps/WeightedEdgeStep.java | 2 +- .../strategy/ConcurrentTraverseStrategy.java | 2 +- .../strategy/SingleTraverseStrategy.java | 2 +- .../algorithm/strategy/TraverseStrategy.java | 2 +- .../traversal/optimize/ConditionP.java | 2 +- .../optimize/HugeCountStepStrategy.java | 2 +- .../traversal/optimize/HugeGraphStep.java | 4 +- .../optimize/HugeScriptTraversal.java | 2 +- .../traversal/optimize/HugeVertexStep.java | 12 +- .../optimize/HugeVertexStepByBatch.java | 6 +- .../traversal/optimize/QueryHolder.java | 4 +- .../hugegraph/traversal/optimize/Text.java | 4 +- .../traversal/optimize/TraversalUtil.java | 24 +- .../org/apache/hugegraph/type/HugeType.java | 210 ---- .../org/apache/hugegraph/type/Idfiable.java | 25 - .../org/apache/hugegraph/type/Indexable.java | 27 - .../org/apache/hugegraph/type/Nameable.java | 31 - .../apache/hugegraph/type/Propertiable.java | 27 - .../org/apache/hugegraph/type/Typeable.java | 24 - .../apache/hugegraph/type/define/Action.java | 74 -- .../hugegraph/type/define/AggregateType.java | 91 -- .../hugegraph/type/define/Cardinality.java | 85 -- .../hugegraph/type/define/CollectionType.java | 66 -- .../hugegraph/type/define/DataType.java | 221 ---- .../hugegraph/type/define/Directions.java | 114 -- .../hugegraph/type/define/EdgeLabelType.java | 62 - .../hugegraph/type/define/HugeKeys.java | 106 -- .../hugegraph/type/define/IdStrategy.java | 69 -- .../hugegraph/type/define/IndexType.java | 120 -- .../hugegraph/type/define/SchemaStatus.java | 63 - .../hugegraph/type/define/SerialEnum.java | 68 -- .../hugegraph/type/define/WriteType.java | 65 -- .../java/org/apache/hugegraph/util/Blob.java | 68 -- .../org/apache/hugegraph/util/ConfigUtil.java | 2 +- .../org/apache/hugegraph/util/Consumers.java | 2 +- .../org/apache/hugegraph/util/CopyUtil.java | 2 +- .../org/apache/hugegraph/util/GZipUtil.java | 4 +- .../org/apache/hugegraph/util/JsonUtil.java | 2 +- .../org/apache/hugegraph/util/LZ4Util.java | 83 -- .../org/apache/hugegraph/util/LockUtil.java | 4 +- .../org/apache/hugegraph/util/Reflection.java | 2 +- .../apache/hugegraph/util/StringEncoding.java | 179 --- .../apache/hugegraph/util/TinkerPopUtil.java | 68 ++ .../util/collection/CollectionFactory.java | 280 ----- .../hugegraph/util/collection/IdSet.java | 117 -- .../collection/ObjectIntMappingFactory.java | 2 +- .../hugegraph/variables/HugeVariables.java | 14 +- .../assembly/static/conf/gremlin-server.yaml | 2 +- .../travis/conf-raft1/gremlin-server.yaml | 2 +- .../travis/conf-raft2/gremlin-server.yaml | 2 +- .../travis/conf-raft3/gremlin-server.yaml | 2 +- .../org/apache/hugegraph/cmd/StoreDumper.java | 2 +- .../hugegraph/dist/HugeGraphServer.java | 2 +- .../hugegraph/dist/HugeGremlinServer.java | 2 +- .../apache/hugegraph/dist/RegisterUtil.java | 2 +- .../apache/hugegraph/example/Example1.java | 12 +- .../apache/hugegraph/example/Example4.java | 4 +- .../apache/hugegraph/example/ExampleUtil.java | 2 +- .../hugegraph/example/PerfExampleBase.java | 4 +- .../apache/hugegraph/example/TaskExample.java | 4 +- .../backend/store/hbase/HbaseSerializer.java | 2 +- .../backend/store/hbase/HbaseSessions.java | 4 +- .../backend/store/hbase/HbaseStore.java | 6 +- .../backend/store/hbase/HbaseTable.java | 22 +- .../backend/store/hbase/HbaseTables.java | 6 +- .../backend/store/hstore/HstoreSessions.java | 9 +- .../store/hstore/HstoreSessionsImpl.java | 15 +- .../backend/store/hstore/HstoreStore.java | 76 +- .../backend/store/hstore/HstoreTable.java | 30 +- .../backend/store/hstore/HstoreTables.java | 218 +++- .../store/hstore/HstoreSessionsImplTest.java | 31 +- .../backend/store/hstore/HstoreTableTest.java | 377 +++++- .../backend/store/rocksdb/OpenedRocksDB.java | 2 +- .../store/rocksdb/RocksDBIngester.java | 2 +- .../store/rocksdb/RocksDBIteratorPool.java | 2 +- .../store/rocksdb/RocksDBStdSessions.java | 4 +- .../backend/store/rocksdb/RocksDBStore.java | 8 +- .../backend/store/rocksdb/RocksDBTable.java | 20 +- .../backend/store/rocksdb/RocksDBTables.java | 11 +- .../store/rocksdbsst/RocksDBSstSessions.java | 2 +- .../store/rocksdbsst/RocksDBSstStore.java | 2 +- .../org/apache/hugegraph/api/BaseApiTest.java | 2 +- .../api/auth/GraphSpaceAuthPayloadTest.java | 2 +- .../api/cypher/CypherClientTest.java | 2 +- .../auth/StandardAuthManagerV2Test.java | 4 +- .../hugegraph/backend/page/QueryListTest.java | 8 +- .../backend/tx/GraphIndexTransactionTest.java | 208 +++- .../backend/tx/GraphTransactionTest.java | 14 +- .../org/apache/hugegraph/core/AuthTest.java | 29 +- .../apache/hugegraph/core/BaseCoreTest.java | 2 +- .../hugegraph/core/CountStrategyCoreTest.java | 12 +- .../apache/hugegraph/core/EdgeCoreTest.java | 24 +- .../hugegraph/core/EdgeLabelCoreTest.java | 8 +- .../hugegraph/core/IndexLabelCoreTest.java | 10 +- .../hugegraph/core/MultiGraphsTest.java | 12 +- .../core/ParentAndSubEdgeCoreTest.java | 2 +- .../hugegraph/core/PropertyCoreTest.java | 2 +- .../hugegraph/core/PropertyKeyCoreTest.java | 6 +- .../apache/hugegraph/core/RamTableTest.java | 6 +- .../apache/hugegraph/core/SchemaCoreTest.java | 10 +- .../apache/hugegraph/core/TaskCoreTest.java | 6 +- .../apache/hugegraph/core/VertexCoreTest.java | 30 +- .../hugegraph/core/VertexLabelCoreTest.java | 10 +- .../core/memory/MemoryConsumerTest.java | 57 +- .../meta/managers/AuthMetaManagerTest.java | 2 +- .../task/TaskAndResultSchedulerTest.java | 6 +- .../org/apache/hugegraph/testutil/Utils.java | 4 +- .../HugeGraphTestInfrastructureTest.java | 4 +- .../apache/hugegraph/tinkerpop/TestGraph.java | 2 +- .../optimize/TraversalUtilOptimizeTest.java | 6 +- .../apache/hugegraph/unit/BaseUnitTest.java | 2 +- .../apache/hugegraph/unit/FakeObjects.java | 26 +- .../apache/hugegraph/unit/UnitTestSuite.java | 4 + .../unit/auth/HugeGraphAuthProxyTest.java | 6 +- .../unit/cache/CacheManagerTest.java | 4 +- .../hugegraph/unit/cache/CacheTest.java | 4 +- .../cache/CachedGraphTransactionTest.java | 18 +- .../cache/CachedSchemaTransactionTest.java | 6 +- .../hugegraph/unit/cache/RamTableTest.java | 8 +- .../GraphBinarySchemaCompatibilityTest.java | 12 +- .../GremlinConfigCompatibilityTest.java | 8 +- .../unit/core/BackendMutationTest.java | 6 +- .../unit/core/BackendProviderFactoryTest.java | 2 +- .../unit/core/ConditionQueryFlattenTest.java | 8 +- .../hugegraph/unit/core/ConditionTest.java | 10 +- .../hugegraph/unit/core/DirectionsTest.java | 14 +- .../unit/core/GraphManagerAdminInitTest.java | 2 +- .../unit/core/GraphManagerStoresWaitTest.java | 2 +- .../unit/core/HugeElementViewTest.java | 220 ++++ .../unit/core/HugePrimaryKeyTest.java | 136 +++ .../hugegraph/unit/core/IdHolderTest.java | 10 +- .../hugegraph/unit/core/LocksTableTest.java | 4 +- .../hugegraph/unit/core/PageStateTest.java | 2 +- .../hugegraph/unit/core/QueryResultsTest.java | 10 +- .../apache/hugegraph/unit/core/QueryTest.java | 20 +- .../apache/hugegraph/unit/core/RangeTest.java | 2 +- .../unit/core/RolePermissionTest.java | 6 +- .../unit/core/SchemaElementTest.java | 88 +- .../unit/core/SecurityManagerTest.java | 2 +- .../unit/core/ServerInfoManagerTest.java | 2 +- .../StandardHugeGraphClearBackendTest.java | 2 +- .../unit/core/SystemSchemaStoreTest.java | 8 +- .../core/TaskSchedulerServerInfoTest.java | 6 +- .../unit/core/TraversalUtilTest.java | 2 +- .../apache/hugegraph/unit/id/EdgeIdTest.java | 6 +- .../org/apache/hugegraph/unit/id/IdTest.java | 6 +- .../apache/hugegraph/unit/id/IdUtilTest.java | 8 +- .../unit/id/SplicingIdGeneratorTest.java | 25 +- .../unit/rocksdb/RocksDBCountersTest.java | 4 +- .../unit/rocksdb/RocksDBPerfTest.java | 2 +- .../unit/rocksdb/RocksDBSessionTest.java | 2 +- .../rocksdb/RocksDBTableQueryByIdsTest.java | 8 +- .../serializer/BinaryBackendEntryTest.java | 3 +- .../BinaryScatterSerializerTest.java | 3 +- .../unit/serializer/BinarySerializerTest.java | 125 +- .../unit/serializer/BytesBufferTest.java | 186 +-- .../serializer/HugeGraphSONModuleTest.java | 12 +- .../serializer/SerializerFactoryTest.java | 2 +- .../unit/serializer/StoreSerializerTest.java | 2 +- .../serializer/TableBackendEntryTest.java | 6 +- .../unit/serializer/TextBackendEntryTest.java | 4 +- .../unit/serializer/TextSerializerTest.java | 6 +- .../traversal/ShortestPathTraverserTest.java | 6 +- .../hugegraph/unit/util/JsonUtilTest.java | 22 +- .../collection/CollectionFactoryTest.java | 2 +- .../unit/util/collection/IdSetTest.java | 4 +- .../util/collection/ObjectIntMappingTest.java | 4 +- .../compatibility/2f827d6e8/README.md | 34 + .../2f827d6e8/core-rows.properties | 108 ++ .../2f827d6e8/store-index-rows.properties | 31 + hugegraph-store/docs/development-guide.md | 16 +- .../store/client/query/QueryExecutor.java | 16 +- hugegraph-store/hg-store-core/pom.xml | 5 - .../apache/hugegraph/store/HgStoreEngine.java | 6 +- .../business/AbstractSelectIterator.java | 11 +- .../store/business/BusinessHandlerImpl.java | 76 +- .../store/business/DataManagerImpl.java | 15 +- .../store/business/FilterIterator.java | 27 +- .../store/business/GraphStoreIterator.java | 2 +- .../store/business/SelectIterator.java | 66 +- .../store/options/HgStoreEngineOptions.java | 2 + .../hugegraph/store/schema}/SchemaDriver.java | 102 +- .../hugegraph/store/schema}/SchemaGraph.java | 22 +- .../hugegraph/store/util/UnsafeUtil.java | 6 +- .../store/grpc/query/QueryResultFormat.java | 26 +- .../hugegraph/store/node/AppConfig.java | 3 + .../store/node/grpc/HgStoreNodeService.java | 1 + .../store/node/grpc/HgStoreWrapperEx.java | 8 +- .../hugegraph/store/node/grpc/ScanUtil.java | 20 +- .../store/node/grpc/query/QueryUtil.java | 33 +- .../node/grpc/query/stages/OlapStage.java | 52 +- .../node/grpc/query/stages/TtlCheckStage.java | 7 +- .../hugegraph/store/node/task/TTLCleaner.java | 16 +- hugegraph-store/hg-store-test/pom.xml | 2 + .../store/business/StoredRowIngressTest.java | 614 ++++++++++ .../store/schema/SchemaDriverTest.java | 548 +++++++++ .../2f827d6e8/LegacyRowFixtureWriter.java.txt | 263 +++++ .../LegacyServerIndexQueryProbe.java.txt | 49 + .../LegacyStoreIndexBuilderProbe.java.txt | 89 ++ .../LegacyStoreIndexFixtureWriter.java.txt | 126 ++ .../compatibility/2f827d6e8/README.md | 147 +++ .../2f827d6e8/core-rows.properties | 108 ++ .../index-builder-contract.properties | 23 + .../2f827d6e8/store-index-rows.properties | 31 + hugegraph-struct/README.md | 267 ++--- hugegraph-struct/pom.xml | 93 +- .../apache/hugegraph/HugeGraphSupplier.java | 30 + .../apache/hugegraph/analyzer/Analyzer.java | 22 +- .../hugegraph/analyzer/AnalyzerFactory.java | 43 +- .../hugegraph/analyzer/AnsjAnalyzer.java | 32 +- .../hugegraph/analyzer/HanLPAnalyzer.java | 53 +- .../apache/hugegraph/analyzer/IKAnalyzer.java | 46 +- .../hugegraph/analyzer/JcsegAnalyzer.java | 63 +- .../hugegraph/analyzer/JiebaAnalyzer.java | 28 +- .../hugegraph/analyzer/MMSeg4JAnalyzer.java | 34 +- .../hugegraph/analyzer/SmartCNAnalyzer.java | 28 +- .../apache/hugegraph/auth/AuthConstant.java | 30 - .../apache/hugegraph/backend/BinaryId.java | 33 +- .../exception/ErrorCodeProvider.java | 4 +- .../exception/LimitExceedException.java | 22 +- .../exception/NotAllowException.java | 22 +- .../exception/NotFoundException.java | 22 +- .../exception/NotSupportException.java | 22 +- .../java/org/apache/hugegraph/id/EdgeId.java | 171 ++- .../main/java/org/apache/hugegraph/id/Id.java | 47 +- .../org/apache/hugegraph/id/IdGenerator.java | 150 +-- .../java/org/apache/hugegraph/id/IdUtil.java | 38 +- .../hugegraph/id/SplicingIdGenerator.java | 38 +- .../apache/hugegraph/options/AuthOptions.java | 114 -- .../apache/hugegraph/options/CoreOptions.java | 660 ----------- .../org/apache/hugegraph/query/Aggregate.java | 62 +- .../hugegraph/query/AggregateFuncDefine.java | 3 +- .../hugegraph}/query/BatchConditionQuery.java | 4 +- .../org/apache/hugegraph/query/Condition.java | 21 +- .../hugegraph/query/ConditionQuery.java | 300 ++--- .../hugegraph}/query/IdPrefixQuery.java | 8 +- .../org/apache/hugegraph/query/IdQuery.java | 64 + .../apache/hugegraph}/query/IdRangeQuery.java | 8 +- .../org/apache/hugegraph/query/Query.java | 37 +- .../query/serializer/AggregateAdapter.java | 69 ++ .../query/serializer/QueryAdapter.java | 15 +- .../serializer/BinaryElementSerializer.java | 505 +++++--- .../hugegraph/serializer/BytesBuffer.java | 570 ++++++--- .../serializer/DirectBinarySerializer.java | 52 +- .../apache/hugegraph/serializer/OlapKey.java | 44 + .../hugegraph/struct/schema/EdgeLabel.java | 67 +- .../hugegraph/struct/schema/IndexLabel.java | 40 +- .../struct/schema/SchemaElement.java | 5 + .../hugegraph/struct/schema/Userdata.java | 46 + .../hugegraph/struct/schema/VertexLabel.java | 6 +- .../apache/hugegraph/structure/BaseEdge.java | 93 +- .../hugegraph/structure/BaseElement.java | 88 +- .../hugegraph/structure/BaseProperty.java | 2 +- .../hugegraph/structure/BaseVertex.java | 78 +- .../org/apache/hugegraph/structure/Index.java | 64 +- .../structure/builder/IndexBuilder.java | 165 +-- .../org/apache/hugegraph/type/HugeType.java | 25 +- .../org/apache/hugegraph/type/Idfiable.java | 22 +- .../apache/hugegraph/type/define/Action.java | 20 +- .../hugegraph/type/define/AggregateType.java | 20 +- .../hugegraph/type/define/Cardinality.java | 19 +- .../hugegraph/type/define/CollectionType.java | 22 +- .../hugegraph/type/define/Frequency.java | 20 +- .../hugegraph/type/define/HugeKeys.java | 26 +- .../hugegraph/type/define/IdStrategy.java | 20 +- .../hugegraph/type/define/IndexType.java | 20 +- .../hugegraph/type/define/SerialEnum.java | 71 +- .../hugegraph/type/define/WriteType.java | 24 +- .../java/org/apache/hugegraph/util/Blob.java | 23 +- .../org/apache/hugegraph/util/KryoUtil.java | 16 +- .../org/apache/hugegraph/util/LZ4Util.java | 44 +- .../hugegraph/util/LegacyClassNames.java | 184 +++ .../apache/hugegraph/util/StringEncoding.java | 64 +- .../org/apache/hugegraph/util/UnsafeUtil.java | 40 +- .../util/collection/CollectionFactory.java | 68 +- .../hugegraph/util/collection/IdSet.java | 39 +- .../util/collection/IntIterator.java | 0 .../hugegraph/util/collection/IntMap.java | 0 .../hugegraph/util/collection/IntSet.java | 5 +- .../apache/hugegraph/SchemaDriverTest.java | 233 ---- .../hugegraph/backend/BackendColumnTest.java | 54 + .../compatibility/LegacyCoreCodecTest.java | 487 ++++++++ .../compatibility/LegacyCoreRowCodecTest.java | 323 ++++++ .../LegacyKryoCompatibilityTest.java | 302 +++++ .../hugegraph/id/IdCompatibilityTest.java | 76 ++ .../hugegraph/query/SharedQueryTest.java | 143 +++ .../hugegraph/serializer/OlapKeyTest.java | 50 + .../struct/schema/EdgeLabelMapTest.java | 95 ++ .../schema/OrderedSchemaFieldsTest.java | 98 ++ .../struct/schema/SchemaElementTest.java | 91 ++ .../structure/SharedElementTest.java | 260 +++++ .../hugegraph/structure/SharedIndexTest.java | 184 +++ .../structure/builder/IndexBuilderTest.java | 284 +++++ .../type/SharedTypeCompatibilityTest.java | 99 ++ .../apache/hugegraph/util/UnsafeUtilTest.java | 27 +- .../LegacyCodecFixtureWriter.java.txt | 181 +++ .../LegacyKryoFixtureWriter.java.txt | 189 +++ .../2f827d6e8/LegacyRowFixtureWriter.java.txt | 263 +++++ .../LegacyServerIndexQueryProbe.java.txt | 49 + .../LegacyStoreIndexBuilderProbe.java.txt | 89 ++ .../LegacyStoreIndexFixtureWriter.java.txt | 126 ++ .../LegacyStructFixtureWriter.java.txt | 74 ++ .../compatibility/2f827d6e8/README.md | 275 +++++ .../2f827d6e8/core-avg-query.json.txt | 17 + .../compatibility/2f827d6e8/core-codecs.hex | 420 +++++++ .../2f827d6e8/core-count-query.json.txt | 17 + .../2f827d6e8/core-edge-query.json.txt | 17 + .../2f827d6e8/core-kryo-objects.properties | 247 ++++ .../2f827d6e8/core-query.json.txt | 17 + .../2f827d6e8/core-rows.properties | 108 ++ .../index-builder-contract.properties | 23 + .../2f827d6e8/store-index-rows.properties | 31 + .../2f827d6e8/struct-tagged-properties.hex | 28 + install-dist/release-docs/LICENSE | 2 + ...E-spring-boot-jarmode-layertools-2.7.1.txt | 202 ++++ .../scripts/dependency/check_dependencies.sh | 22 +- .../dependency/dependency_inventory.py | 163 +++ .../regenerate_known_dependencies.sh | 29 +- .../dependency/test_dependency_inventory.py | 156 +++ .../check_shared_foundation.py | 466 ++++++++ .../retired-core-classes.txt | 96 ++ .../test_shared_foundation.py | 638 ++++++++++ 652 files changed, 15557 insertions(+), 16983 deletions(-) create mode 100644 docs/shared-foundation-migration.md rename {hugegraph-server/hugegraph-core => hugegraph-commons/hugegraph-common}/src/main/java/org/apache/hugegraph/auth/AuthConstant.java (88%) rename {hugegraph-server/hugegraph-core => hugegraph-commons/hugegraph-common}/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java (64%) rename hugegraph-commons/{hugegraph-rpc => hugegraph-common}/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java (100%) rename hugegraph-commons/{hugegraph-rpc => hugegraph-common}/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java (100%) create mode 100644 hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/auth/TokenGeneratorTest.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeException.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/BackendException.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/Id.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdUtil.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/SplicingIdGenerator.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Aggregate.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdQuery.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/AbstractSerializerAdapter.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryAdapter.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryIdAdapter.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/Shard.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotAllowException.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotSupportException.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/IndexLabel.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/PropertyKey.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaElement.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaLabel.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/Userdata.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/VertexLabel.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/SchemaBuilder.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/GraphType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeIndex.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/HugeType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Idfiable.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Indexable.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Nameable.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Propertiable.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Typeable.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Action.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/AggregateType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Cardinality.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/CollectionType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/DataType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Directions.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IndexType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SchemaStatus.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/WriteType.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Blob.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LZ4Util.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/TinkerPopUtil.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IdSet.java create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugeElementViewTest.java create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugePrimaryKeyTest.java create mode 100644 hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/README.md create mode 100644 hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties create mode 100644 hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties rename {hugegraph-struct/src/main/java/org/apache/hugegraph => hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema}/SchemaDriver.java (91%) rename {hugegraph-struct/src/main/java/org/apache/hugegraph => hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema}/SchemaGraph.java (91%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotFoundException.java => hugegraph-store/hg-store-grpc/src/main/dev/org/apache/hugegraph/store/grpc/query/QueryResultFormat.java (50%) create mode 100644 hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java create mode 100644 hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/schema/SchemaDriverTest.java create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/README.md create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/index-builder-contract.properties create mode 100644 hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties delete mode 100644 hugegraph-struct/src/main/java/org/apache/hugegraph/auth/AuthConstant.java delete mode 100644 hugegraph-struct/src/main/java/org/apache/hugegraph/options/AuthOptions.java delete mode 100644 hugegraph-struct/src/main/java/org/apache/hugegraph/options/CoreOptions.java rename {hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend => hugegraph-struct/src/main/java/org/apache/hugegraph}/query/BatchConditionQuery.java (96%) rename {hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend => hugegraph-struct/src/main/java/org/apache/hugegraph}/query/IdPrefixQuery.java (94%) rename {hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend => hugegraph-struct/src/main/java/org/apache/hugegraph}/query/IdRangeQuery.java (94%) create mode 100644 hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/AggregateAdapter.java create mode 100644 hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/OlapKey.java rename {hugegraph-server/hugegraph-core => hugegraph-struct}/src/main/java/org/apache/hugegraph/util/KryoUtil.java (83%) create mode 100644 hugegraph-struct/src/main/java/org/apache/hugegraph/util/LegacyClassNames.java rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Frequency.java => hugegraph-struct/src/main/java/org/apache/hugegraph/util/UnsafeUtil.java (52%) rename {hugegraph-server/hugegraph-core => hugegraph-struct}/src/main/java/org/apache/hugegraph/util/collection/IntIterator.java (100%) rename {hugegraph-server/hugegraph-core => hugegraph-struct}/src/main/java/org/apache/hugegraph/util/collection/IntMap.java (100%) rename {hugegraph-server/hugegraph-core => hugegraph-struct}/src/main/java/org/apache/hugegraph/util/collection/IntSet.java (99%) delete mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/SchemaDriverTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/backend/BackendColumnTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreCodecTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreRowCodecTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/id/IdCompatibilityTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/query/SharedQueryTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/serializer/OlapKeyTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/EdgeLabelMapTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/OrderedSchemaFieldsTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/SchemaElementTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedElementTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedIndexTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/structure/builder/IndexBuilderTest.java create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/type/SharedTypeCompatibilityTest.java rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java => hugegraph-struct/src/test/java/org/apache/hugegraph/util/UnsafeUtilTest.java (53%) create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyCodecFixtureWriter.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyKryoFixtureWriter.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStructFixtureWriter.java.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/README.md create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-avg-query.json.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-codecs.hex create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-count-query.json.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-edge-query.json.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-kryo-objects.properties create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-query.json.txt create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-rows.properties create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/index-builder-contract.properties create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/store-index-rows.properties create mode 100644 hugegraph-struct/src/test/resources/compatibility/2f827d6e8/struct-tagged-properties.hex create mode 100644 install-dist/release-docs/licenses/LICENSE-spring-boot-jarmode-layertools-2.7.1.txt create mode 100644 install-dist/scripts/dependency/dependency_inventory.py create mode 100644 install-dist/scripts/dependency/test_dependency_inventory.py create mode 100644 install-dist/scripts/shared-foundation/check_shared_foundation.py create mode 100644 install-dist/scripts/shared-foundation/retired-core-classes.txt create mode 100644 install-dist/scripts/shared-foundation/test_shared_foundation.py diff --git a/.github/workflows/check-dependencies.yml b/.github/workflows/check-dependencies.yml index 73ef769c67..fcc234be7e 100644 --- a/.github/workflows/check-dependencies.yml +++ b/.github/workflows/check-dependencies.yml @@ -29,15 +29,27 @@ jobs: cp $HOME/.m2/settings.xml /tmp/settings.xml mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml + - name: Test shared foundation checks + run: python3 -m unittest discover -s install-dist/scripts/shared-foundation -p 'test_*.py' + + - name: Test dependency inventory producer and checker + run: python3 -m unittest discover -s install-dist/scripts/dependency -p 'test_*.py' + - name: mvn install run: | mvn install -Dmaven.test.skip=true -ntp --fail-at-end + - name: Check shared foundation boundaries and shipped classes + run: | + REVISION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + python3 install-dist/scripts/shared-foundation/check_shared_foundation.py --revision "$REVISION" + - name: generate current dependencies run: | - bash $SCRIPT_DEPENDENCY/regenerate_known_dependencies.sh current-dependencies.txt + bash $SCRIPT_DEPENDENCY/regenerate_known_dependencies.sh "$PWD/target/dependency/current-dependencies.txt" - name: check third dependencies run: | - bash $SCRIPT_DEPENDENCY/check_dependencies.sh + bash $SCRIPT_DEPENDENCY/check_dependencies.sh \ + "$SCRIPT_DEPENDENCY/known-dependencies.txt" "$PWD/target/dependency/current-dependencies.txt" dependency-review: runs-on: ubuntu-latest diff --git a/README.md b/README.md index 18a20d56e9..98413218c8 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,9 @@ See the [backend evolution guide](hugegraph-server/README.md#backend-evolution-a | [hugegraph-pd](hugegraph-pd/README.md) | Placement Driver for distributed mode - handles meta storage, partition management and cluster scheduling | | [hugegraph-store](hugegraph-store/README.md) | Distributed storage with Raft consensus for high availability and horizontal scaling | | [hugegraph-commons](hugegraph-commons) | Shared utilities, RPC framework and common components | +| [hugegraph-struct](hugegraph-struct/README.md) | Shared schema, IDs, base elements, queries and encoding used by Server and Store | + +See the [1.8.0 shared-foundation migration guide](docs/shared-foundation-migration.md) for Java API changes, module ownership and coordinated upgrade requirements.
📊 Click to view detailed architecture diagram (Mermaid) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index af3fa2cd2d..bdc67ae602 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -50,6 +50,21 @@ and automatic cancellation and retries. Report what you actually validated and a Update the [dependency inventory](../install-dist/scripts/dependency/known-dependencies.txt) using [the regeneration script](../install-dist/scripts/dependency/regenerate_known_dependencies.sh). +Install/package the current reactor before regenerating the inventory: + +```bash +mvn install -DskipTests -Dmaven.javadoc.skip=true +bash install-dist/scripts/dependency/regenerate_known_dependencies.sh +``` + +The build must produce Server, PD and Store distributions for the same current revision. +It skips tests and is not validation evidence. The inventory combines Maven runtime +dependencies with flat and nested distribution jars, including Spring Boot `BOOT-INF/lib` +dependencies inserted by repackaging. Missing distributions fail collection; source or POM +inspection alone cannot establish the full shipped inventory. Review all additions and +removals and their license/NOTICE coverage. The dependency check compares the exact inventory; +repeat it for release platform/profile variants as needed. + ## Submit and review Use `type(scope): description` for commits; omit the scope when it is unclear. diff --git a/docs/shared-foundation-migration.md b/docs/shared-foundation-migration.md new file mode 100644 index 0000000000..3ce77f1951 --- /dev/null +++ b/docs/shared-foundation-migration.md @@ -0,0 +1,254 @@ +# Shared foundations: 1.8.0 migration + +The consolidation tracked in [#257](https://github.com/hugegraph/hugegraph/issues/257) +removes duplicated shared implementations from Server core. Core remains the +graph engine; struct becomes the canonical shared foundation. The 4.0 fork is +a reference for composition and delegation, not a replacement for community +behavior. Differences must be resolved from current callers, persisted data and +tests rather than choosing whichever implementation is easiest to transplant. + +## Ownership and dependencies + +```text +Server core ──> struct ──> common +Store core ──> struct +PD service ──> common +``` + +These arrows describe the shared-foundation boundary, not the complete Maven +dependency tree. Core still needs PD/Store clients for HStore execution; Store +still needs its network, PD client and storage libraries. Struct retains shared +index/analyzer and codec dependencies, including shaded Kryo where required. + +| Capability | Canonical owner | Caller behavior | +|------------|-----------------|-----------------| +| IDs, schema metadata, type codes | struct | Import shared types | +| Queries, base elements, byte and property codecs | struct | Reuse implementation; adapt engine/backend behavior | +| Index construction and analyzers | struct | Preserve configured analysis and index results | +| Graph transactions, traversal, tasks, schema mutation | core | Operate on shared metadata and elements | +| PD-backed schema access, listeners and cache lifecycle | Store | Own `SchemaGraph`/`SchemaDriver` resources | +| JWT signing/verification and shared auth constants | common | Supply configuration; translate failures locally | +| RPC client/server configuration interfaces | common | Preserve existing RPC implementations and signatures | + +`HugeGraphSupplier` is the shared access boundary. Core and Store implement it +without injecting the graph engine into struct. It currently includes schema, +configuration and clock capabilities; narrowing this contract is a follow-up, +not permission to duplicate its consumers. + +Core elements wrap shared base elements. Property mutation, cloning, removal, +expiration and loading state propagate through that shared state. `BaseVertex` +owns adjacency; the engine keeps an identity cache of edge wrappers over the +same base edges, not another adjacency collection. Core serializers retain +engine/backend adapters and delegate shared encoding. + +Shared index construction and OLAP selection accept caller-supplied schema +candidates and result sinks. Core retains transaction writes, backend capability +checks and index update orchestration. These execution responsibilities do not +justify a second index model or selection algorithm. + +## Java API changes + +Compile applications and internal integrations against the migrated artifacts. +There is no general compatibility package containing the removed core classes. + +| Previous core entry | Shared entry or migration | +|---------------------|---------------------------| +| `org.apache.hugegraph.backend.id.*` | `org.apache.hugegraph.id.*` | +| `org.apache.hugegraph.schema.*` metadata | `org.apache.hugegraph.struct.schema.*` | +| `org.apache.hugegraph.backend.query.*` | `org.apache.hugegraph.query.*` | +| `org.apache.hugegraph.backend.store.Shard` | `org.apache.hugegraph.backend.Shard` | +| `org.apache.hugegraph.backend.store.BackendEntry.BackendColumn` | `org.apache.hugegraph.backend.BackendColumn` | +| `org.apache.hugegraph.structure.HugeIndex` | `org.apache.hugegraph.structure.Index` | +| `HugeGraph.sameAs(HugeGraph)` | `HugeGraph.sameAs(HugeGraphSupplier)` | +| Shared bytes/encoding in backend serializers | `org.apache.hugegraph.serializer.*` | +| Core `HugeException` | `org.apache.hugegraph.exception.HugeException` | +| `org.apache.hugegraph.SchemaGraph`/`SchemaDriver` | `org.apache.hugegraph.store.schema.*` | + +This table identifies ownership changes; it is not a blanket package replacement. +Relocated types also change method descriptors that expose IDs, schema, queries +and indexes. Update implementations and call sites, then recompile every affected +integration against the matching 1.8.0 artifacts; import changes alone do not make +old compiled clients binary-compatible. + +External implementations of `org.apache.hugegraph.HugeGraph` must change their +`sameAs` override parameter from `HugeGraph` to +`org.apache.hugegraph.HugeGraphSupplier`. Shared schema and queries receive this +supplier contract without needing a concrete graph engine, so identity comparison +must accept it too. `StandardHugeGraph` and `HugeGraphAuthProxy` use the same +signature. There is no compatibility overload for the old descriptor. +Custom `HugeElement` subclasses must provide shared `BaseElement` state through +`element()` and adapt shared properties through `wrapProperty`; do not restore +the removed protected engine state fields or maintain a second adjacency store. + +Schema mutation builders and backend-specific serializers remain in core. +The shared `Shard` keeps its existing GraphSON type tag and fields; query decoding +also preserves the legacy fully qualified name. Toolchain +`org.apache.hugegraph.structure.graph.Shard` remains a separate REST DTO. +`BackendColumn` retains its mutable `name`/`value` byte-array fields. Its shared +implementation hashes array contents consistently with equality, replacing the +old core array-identity hash. Historical Kryo names need decoder aliases and +fixture verification; the byte fields themselves are unchanged. Store +`RocksDBSession.BackendColumn` remains a backend-specific adapter. +`GraphSerializer.writeIndex`/`readIndex` now accept/return shared +`org.apache.hugegraph.structure.Index`. Migrate implementations of this Java SPI +and their callers; no long-lived `HugeIndex` compatibility wrapper is retained. +Index hash-ID generation also belongs to the shared implementation. +`org.apache.hugegraph.rpc.RpcServiceConfig4Client` and +`org.apache.hugegraph.rpc.RpcServiceConfig4Server` now have one owner in common. +Their fully qualified names and signatures are unchanged; RPC implementations +and configuration values do not need a source migration. The duplicate core and +commons-rpc definitions are removed without adding a dependency edge. +`HugeVertex` and `HugeEdge` remain engine adapters; Store uses base elements. +`TokenGenerator` resides in common under `org.apache.hugegraph.auth`; callers +supply the signing secret and translate JWT failures into their existing service +responses. JWT dependencies are optional in common, so direct JWT consumers +must declare their required JWT libraries explicitly. + +### Downstream classpath and exception migration + +Distinct downstream behaviors also need distinct Java class names. The local +Toolchain handoff addresses these collisions without replacing client REST DTOs: + +| Previous downstream entry | Replacement | +|---------------------------|-------------| +| Hubble `org.apache.hugegraph.exception.HugeException` | `org.apache.hugegraph.exception.HubbleException` | +| Client `org.apache.hugegraph.exception.NotSupportException` | `org.apache.hugegraph.exception.ClientNotSupportException` | +| Hubble's copy of `org.apache.hugegraph.license.MachineInfo` | Same fully qualified name supplied by `hugegraph-common` | + +Update imports, constructor calls and exception handlers using these downstream +classes. `HubbleException` remains a `RuntimeException` with its string constructor; +`ClientNotSupportException` remains a `ClientException` with the existing +message/cause and message/arguments constructors. Do not redirect their catches +to struct's `HugeException` or `NotSupportException`: those are different +contracts. `MachineInfo` callers retain their imports and use the common +implementation instead of carrying another class with the same name. + +Computer's `HgkvDirImpl` is an affected client-exception caller and must migrate +to `org.apache.hugegraph.exception.ClientNotSupportException`. These Toolchain +and Computer changes are local handoffs in this delivery, not published downstream +PRs. Their builds and packaged-classpath validation remain required before +claiming migration readiness. A source scan showing no duplicate fully qualified +names cannot prove the built jars have no stale or transitive collisions. + +Loader's client-based REST boundary and independent client DTOs do not need a +wholesale conversion to struct. Migrate only the actual affected Java calls. + +### Gremlin configuration imports + +Replace `org.apache.hugegraph.backend.id.IdGenerator` with +`org.apache.hugegraph.id.IdGenerator` in custom Gremlin `classImports` and +scripts. The bundled default and Raft example configurations use the shared +class. Java compilation does not validate configuration-only class names, so +verify the packaged Gremlin service as well as application source imports. + +## Data and runtime compatibility + +### Persisted rows and transient query results + +Server-persisted property rows use schema-driven values. Temporary Store shuffle +and aggregation results use tagged values. Shared readers select this mode from +the known producer/request plan; they do not guess from value bytes. Both modes +share the scalar codec and must preserve historical samples. Ordinary schema +index writers use the existing Server key/name-TTL layout. Store SYSTEM-label +indexes with positive expiry retain their historical stable key plus 13-byte +value envelope; the core SYSTEM-label writer retains its existing bytes. The +label-index reader recognizes that precisely bounded legacy expiry envelope. +This does not add a TTL suffix to those keys or change prefix deletion behavior. +Shared `Index.hasTtl()` follows the existing engine contract for system indexes; +the Store envelope is handled at the serializer boundary. Existing unsupported +index-only element reconstruction is not enabled by this consolidation. + +Schema map decoding preserves the existing wire field names and ID identity. +Two decoder defects are corrected separately from type relocation: primary-key +and edge sort-key lists retain their order and duplicate entries rather than +passing through a set; redundant edge endpoint metadata is resolved consistently +regardless of map field order. Matching `links` and source/target fields are +accepted, legacy source/target-only maps remain readable, and conflicting or +malformed endpoint metadata is rejected. Ordered-schema and endpoint-map tests +cover these corrections, including generated vertex/edge IDs and query values. +These focused tests do not prove all distributed or packaged release gates. + +### Metadata namespace + +Store accepts the existing `pd.cluster` metadata namespace setting, defaulting +to `hg`. In Store `application.yml`, configure it as: + +```yaml +pd: + cluster: hg +``` + +The environment equivalent is `PD_CLUSTER`. It must match Server's `cluster` +when `usePD=true`, or the graph's `pd.cluster` when `usePD=false`. The namespace +applies to schema, graph configuration, cache watches and TTL-cleaner metadata. +One Store process cannot reuse its schema driver for conflicting namespaces. + +Backend graph names keep the existing `graphspace/store/table` components, for +example `DEFAULT/hugegraph/g`; REST identity `DEFAULT-hugegraph` is not a metadata +key. Preserve these names and configure the namespace consistently on both sides. + +### Upgrade contracts + +Upgrade Server, PD and Store together to the matching release artifacts. +Mixed-version rolling upgrades are not a supported acceptance target for this +change. Back up data and configuration using the existing deployment procedure +before upgrading; this consolidation introduces no data-rewrite operation. + +Preserve existing type codes, ID and property bytes, index keys, TTL/OLAP layout, +query semantics and configuration defaults. Java API changes do not authorize +changes to storage tables or wire contracts. + +`BaseVertex.TypeContext` makes the legacy classification context explicit: + +- `STORAGE` retains Store's treatment of `~variables` as task data. +- `ENGINE` retains the engine's treatment of `~server` and `~role_data` as server + data, and `~variables` as ordinary vertex data. +- Both retain `~task` and `~taskresult` as task data. + +Engine wrappers must select `ENGINE`; standalone storage elements retain +`STORAGE`. This shared classifier preserves existing readers/table routing +instead of silently changing where system vertices are read or written. + +Query JSON still contains Java names for some relation values. Decoder mappings +must read the historical names after type relocation. Replacing those names with +stable value tags is tracked in [#259](https://github.com/hugegraph/hugegraph/issues/259) +and requires an explicit compatibility policy; it is not part of a mechanical +import migration. Keep existing Kryo decoding where historical values require it. + +## Validation and release prerequisites + +The ownership description above is not a claim that all release gates have +passed. Review the actual commit, test reports and built distribution before +releasing. Required evidence includes: + +- Canonical shared tests plus frozen pre-migration byte/JSON fixtures, including + IDs, schema, properties, indexes, pagination, TTL/OLAP and supported Kryo data. +- RocksDB and HStore execution, Store filtering/schema access, authentication, + element state propagation and affected downstream tests. +- Resolved dependency trees excluding core from PD/Store and PD client/core from + struct; built distribution checks for duplicate HugeGraph classes. +- Startup of the packaged services, not just source compilation, with no classpath + ordering workaround for duplicate classes. +- Independent review and CI checks preventing reintroduction of duplicate owners + or forbidden dependencies. + +Build and test commands and service prerequisites are maintained in +[BUILDING](BUILDING.md), module guidance and CI. Ensure tests actually run; +`-DskipTests` is not compatibility evidence. + +## Follow-up work and website documentation handoff + +[Narrow supplier capabilities](https://github.com/hugegraph/hugegraph/issues/258) +and [stable query value tags](https://github.com/hugegraph/hugegraph/issues/259) +have concrete source evidence and acceptance criteria. Code TODOs must reference +an unambiguous issue and an actionable remaining improvement. They cannot defer +required de-duplication or historical-data validation. + +Website upgrade/developer documentation needs the Java migration table, +coordinated Server/PD/Store upgrade requirement, historical-data compatibility +checks and ownership summary above. This document is the local source for that +paired update. Publication in this round is restricted to `hugegraph/hugegraph`; +no `apache/hugegraph-doc` PR is published here. The required paired website PR +and coordinated merge remain unmet prerequisites for an upstream release/merge, +even if the fork PR passes its own tests. Do not label it upstream release-ready +until that documentation gate is satisfied. diff --git a/hugegraph-commons/hugegraph-common/pom.xml b/hugegraph-commons/hugegraph-common/pom.xml index 318d9c22fa..25c10e139a 100644 --- a/hugegraph-commons/hugegraph-common/pom.xml +++ b/hugegraph-commons/hugegraph-common/pom.xml @@ -39,6 +39,7 @@ 4.10.0 + 0.11.5 @@ -72,6 +73,28 @@ ${log4j2.version} + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + true + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + true + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + true + + org.glassfish diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthConstant.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/auth/AuthConstant.java similarity index 88% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthConstant.java rename to hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/auth/AuthConstant.java index 3c7c539363..089fb8aa59 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthConstant.java +++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/auth/AuthConstant.java @@ -24,4 +24,6 @@ public interface AuthConstant { */ String TOKEN_USER_NAME = "user_name"; String TOKEN_USER_ID = "user_id"; + // Retained for callers using the former struct constants; not emitted by login. + String TOKEN_USER_PASSWORD = "user_password"; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java similarity index 64% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java rename to hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java index 7c75c095b9..83fecb47e7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java +++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/auth/TokenGenerator.java @@ -23,27 +23,16 @@ import javax.crypto.SecretKey; -import org.apache.hugegraph.config.AuthOptions; -import org.apache.hugegraph.config.HugeConfig; - import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jws; -import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; -import jakarta.ws.rs.NotAuthorizedException; public class TokenGenerator { private final SecretKey key; - public TokenGenerator(HugeConfig config) { - String secretKey = config.get(AuthOptions.AUTH_TOKEN_SECRET); - this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); - } - public TokenGenerator(String secretKey) { this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); } @@ -56,17 +45,15 @@ public String create(Map payload, long expire) { .compact(); } + /** + * Verify a signed token. Callers translate JJWT failures into their own + * authentication or transport errors. + */ public Claims verify(String token) { - try { - Jws claimsJws = Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token); - return claimsJws.getBody(); - } catch (ExpiredJwtException e) { - throw new NotAuthorizedException("The token is expired", e); - } catch (JwtException e) { - throw new NotAuthorizedException("Invalid token", e); - } + Jws claimsJws = Jwts.parserBuilder() + .setSigningKey(this.key) + .build() + .parseClaimsJws(token); + return claimsJws.getBody(); } } diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java similarity index 100% rename from hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java rename to hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java similarity index 100% rename from hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java rename to hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java index 4f5fd0728f..7705215e2d 100644 --- a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java +++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java @@ -19,6 +19,7 @@ import org.apache.hugegraph.testutil.AssertTest; import org.apache.hugegraph.testutil.WhiteboxTest; +import org.apache.hugegraph.unit.auth.TokenGeneratorTest; import org.apache.hugegraph.unit.config.HugeConfigTest; import org.apache.hugegraph.unit.config.OptionSpaceTest; import org.apache.hugegraph.unit.event.EventHubTest; @@ -78,6 +79,7 @@ RowLockTest.class, PausableScheduledThreadPoolTest.class, + TokenGeneratorTest.class, HugeConfigTest.class, OptionSpaceTest.class, SafeDateFormatTest.class, diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/auth/TokenGeneratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/auth/TokenGeneratorTest.java new file mode 100644 index 0000000000..a047e00e68 --- /dev/null +++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/auth/TokenGeneratorTest.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.unit.auth; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hugegraph.auth.AuthConstant; +import org.apache.hugegraph.auth.TokenGenerator; +import org.apache.hugegraph.testutil.Assert; +import org.junit.Test; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.security.WeakKeyException; + +public class TokenGeneratorTest { + + private static final String SECRET = "01234567890123456789012345678901"; + + @Test + public void testCreateAndVerifyClaims() { + TokenGenerator generator = new TokenGenerator(SECRET); + Map payload = new HashMap<>(); + payload.put(AuthConstant.TOKEN_USER_NAME, "alice"); + payload.put(AuthConstant.TOKEN_USER_ID, "1234"); + long before = System.currentTimeMillis(); + Claims claims = generator.verify(generator.create(payload, 60000L)); + long after = System.currentTimeMillis(); + + Assert.assertEquals("alice", claims.get(AuthConstant.TOKEN_USER_NAME)); + Assert.assertEquals("1234", claims.get(AuthConstant.TOKEN_USER_ID)); + Assert.assertFalse(claims.containsKey(AuthConstant.TOKEN_USER_PASSWORD)); + // JWT timestamps have second precision. + Assert.assertTrue(claims.getExpiration().getTime() >= before + 59000L); + Assert.assertTrue(claims.getExpiration().getTime() <= after + 60000L); + } + + @Test + public void testReadLegacyHs256Token() { + // Fixed claims and independent HMAC-SHA256 signature, not this class's writer. + String token = "eyJhbGciOiJIUzI1NiJ9." + + "eyJ1c2VyX25hbWUiOiJsZWdhY3ktdXNlciIsInVzZXJfaWQiOiIxMjM0IiwiZXhwIjo0MTAyNDQ0ODAwfQ." + + "t2b5xSruyIrZ8c45HOe6OhJt390rm_fdbvft1JLyRTs"; + Claims claims = new TokenGenerator(SECRET).verify(token); + Assert.assertEquals("legacy-user", claims.get(AuthConstant.TOKEN_USER_NAME)); + Assert.assertEquals("1234", claims.get(AuthConstant.TOKEN_USER_ID)); + Assert.assertEquals(4102444800000L, claims.getExpiration().getTime()); + } + + @Test + public void testRejectExpiredToken() { + TokenGenerator generator = new TokenGenerator(SECRET); + String token = generator.create(Collections.singletonMap("user_name", "alice"), + -60000L); + Assert.assertThrows(ExpiredJwtException.class, () -> generator.verify(token)); + } + + @Test + public void testRejectWrongKeyAndMalformedTokens() { + TokenGenerator generator = new TokenGenerator(SECRET); + String token = generator.create(Collections.singletonMap("user_name", "alice"), + 60000L); + TokenGenerator other = new TokenGenerator("abcdefghijklmnopqrstuvwxyz012345"); + Assert.assertThrows(JwtException.class, () -> other.verify(token)); + Assert.assertThrows(JwtException.class, () -> generator.verify("not-a-token")); + Assert.assertThrows(IllegalArgumentException.class, () -> generator.verify("")); + } + + @Test + public void testRejectUnsignedToken() { + TokenGenerator generator = new TokenGenerator(SECRET); + String token = generator.create(Collections.singletonMap("user_name", "alice"), + 60000L); + String unsigned = "eyJhbGciOiJub25lIn0." + token.split("\\.")[1] + "."; + Assert.assertThrows(JwtException.class, () -> generator.verify(unsigned)); + } + + @Test + public void testRejectWeakKey() { + Assert.assertThrows(WeakKeyException.class, () -> new TokenGenerator("short-key")); + } +} diff --git a/hugegraph-pd/hg-pd-service/pom.xml b/hugegraph-pd/hg-pd-service/pom.xml index 12b0933dd8..34a00e00e0 100644 --- a/hugegraph-pd/hg-pd-service/pom.xml +++ b/hugegraph-pd/hg-pd-service/pom.xml @@ -58,15 +58,21 @@ - org.apache.hugegraph - hg-store-common - ${revision} + io.jsonwebtoken + jjwt-api + 0.11.5 - - org.apache.hugegraph - hugegraph-core - ${revision} + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/API.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/API.java index b50195b85d..b5653d5977 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/API.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/API.java @@ -24,7 +24,7 @@ import java.util.function.Consumer; import org.apache.commons.lang.mutable.MutableLong; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/AccessAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/AccessAPI.java index 117da8e9ae..578685feb1 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/AccessAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/AccessAPI.java @@ -26,7 +26,7 @@ import org.apache.hugegraph.auth.HugeAccess; import org.apache.hugegraph.auth.HugePermission; import org.apache.hugegraph.auth.HugeTarget; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.exception.NotFoundException; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/BelongAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/BelongAPI.java index d5e3f105bb..5f2d6d5663 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/BelongAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/BelongAPI.java @@ -24,7 +24,7 @@ import org.apache.hugegraph.api.filter.StatusFilter.Status; import org.apache.hugegraph.auth.AuthManager; import org.apache.hugegraph.auth.HugeBelong; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.exception.NotFoundException; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceGroupAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceGroupAPI.java index d41de962e2..eb3b7c1ec2 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceGroupAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceGroupAPI.java @@ -29,7 +29,7 @@ import org.apache.hugegraph.auth.HugeGroup; import org.apache.hugegraph.auth.HugeUser; import org.apache.hugegraph.auth.StandardAuthManagerV2; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.exception.NotFoundException; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GroupAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GroupAPI.java index ae13beb4a6..f19200c65a 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GroupAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/GroupAPI.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; import org.apache.hugegraph.auth.HugeGroup; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.exception.NotFoundException; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/ProjectAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/ProjectAPI.java index 4380093ba0..322d434bff 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/ProjectAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/ProjectAPI.java @@ -27,7 +27,7 @@ import org.apache.hugegraph.api.filter.StatusFilter.Status; import org.apache.hugegraph.auth.AuthManager; import org.apache.hugegraph.auth.HugeProject; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.exception.NotFoundException; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/UserAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/UserAPI.java index 7504ad7325..d5e5288f49 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/UserAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/UserAPI.java @@ -23,8 +23,8 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; import org.apache.hugegraph.auth.HugeUser; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.exception.NotFoundException; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/cypher/CypherClient.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/cypher/CypherClient.java index 85d98a25ce..ebe0c7bb3c 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/cypher/CypherClient.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/cypher/CypherClient.java @@ -32,7 +32,7 @@ import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.configuration2.Configuration; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; import org.apache.tinkerpop.gremlin.driver.Client; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/ExceptionFilter.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/ExceptionFilter.java index 20dc1808ab..e59c86d991 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/ExceptionFilter.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/ExceptionFilter.java @@ -26,7 +26,7 @@ import javax.json.JsonObjectBuilder; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.api.API; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.ServerOptions; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/BatchAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/BatchAPI.java index 85beb142db..fc0ff2cc98 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/BatchAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/BatchAPI.java @@ -21,7 +21,7 @@ import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.config.HugeConfig; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java index 1f229cd6b1..c9c741a657 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java @@ -29,17 +29,17 @@ import org.apache.hugegraph.api.filter.CompressInterceptor.Compress; import org.apache.hugegraph.api.filter.DecompressInterceptor.Decompress; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.ServerOptions; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.UpdateStrategy; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.optimize.QueryHolder; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/VertexAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/VertexAPI.java index af1433ac46..31ab5c032b 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/VertexAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/VertexAPI.java @@ -30,16 +30,16 @@ import org.apache.hugegraph.api.filter.CompressInterceptor.Compress; import org.apache.hugegraph.api.filter.DecompressInterceptor.Decompress; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.ServerOptions; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.UpdateStrategy; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.optimize.QueryHolder; import org.apache.hugegraph.traversal.optimize.Text; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/AlgorithmAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/AlgorithmAPI.java index 6554d58072..95be404582 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/AlgorithmAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/AlgorithmAPI.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.job.AlgorithmJob; import org.apache.hugegraph.job.JobBuilder; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/ComputerAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/ComputerAPI.java index 222ead7e55..478562566a 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/ComputerAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/ComputerAPI.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.job.ComputerJob; import org.apache.hugegraph.job.JobBuilder; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java index c6abac4067..d727ebeb53 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java @@ -25,11 +25,11 @@ import java.util.HashMap; import java.util.Map; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; import org.apache.hugegraph.job.GremlinJob; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java index 6c103ca414..1508e9ff7f 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.util.Log; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/TaskAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/TaskAPI.java index 0accec132a..f3613434c1 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/TaskAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/TaskAPI.java @@ -27,8 +27,8 @@ import org.apache.groovy.util.Maps; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.task.HugeTask; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java index 94169e4a90..95505be80b 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java @@ -29,7 +29,7 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java index fcc18c4c8c..f3987635f7 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java @@ -21,11 +21,11 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.store.raft.RaftAddPeerJob; import org.apache.hugegraph.backend.store.raft.RaftGroupManager; import org.apache.hugegraph.backend.store.raft.RaftRemovePeerJob; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java index 3031b687d0..3a7db5f85c 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java @@ -27,11 +27,11 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.type.define.EdgeLabelType; import org.apache.hugegraph.type.define.Frequency; import org.apache.hugegraph.type.define.GraphMode; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/IndexLabelAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/IndexLabelAPI.java index 3bc769801d..bf66d3ea95 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/IndexLabelAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/IndexLabelAPI.java @@ -26,12 +26,12 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.GraphMode; import org.apache.hugegraph.type.define.IndexType; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/PropertyKeyAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/PropertyKeyAPI.java index 1364b02fea..9cf19c819f 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/PropertyKeyAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/PropertyKeyAPI.java @@ -26,13 +26,13 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.type.define.AggregateType; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/VertexLabelAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/VertexLabelAPI.java index 4001ce27f5..ff3320ae74 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/VertexLabelAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/VertexLabelAPI.java @@ -26,11 +26,11 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.StatusFilter.Status; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.Checkable; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.define.GraphMode; import org.apache.hugegraph.type.define.IdStrategy; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/space/SchemaTemplateAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/space/SchemaTemplateAPI.java index cffca156cd..e1dab458f6 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/space/SchemaTemplateAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/space/SchemaTemplateAPI.java @@ -23,7 +23,7 @@ import java.util.function.Supplier; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.api.API; import org.apache.hugegraph.auth.AuthManager; import org.apache.hugegraph.api.filter.StatusFilter; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AdamicAdarAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AdamicAdarAPI.java index 6bf8bf3b82..11cdc3dec0 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AdamicAdarAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AdamicAdarAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -24,7 +26,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.PredictionTraverser; import org.apache.hugegraph.type.define.Directions; @@ -77,7 +79,7 @@ public String get(@Context GraphManager manager, Id targetId = VertexAPI.checkAndParseVertexId(other); E.checkArgument(!current.equals(other), "The source and target vertex id can't be same"); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); try (PredictionTraverser traverser = new PredictionTraverser(g)) { diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AllShortestPathsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AllShortestPathsAPI.java index 3880b1239e..f02f116a1e 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AllShortestPathsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/AllShortestPathsAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -29,7 +31,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.ShortestPathTraverser; @@ -103,7 +105,7 @@ public String get(@Context GraphManager manager, Id sourceId = VertexAPI.checkAndParseVertexId(source); Id targetId = VertexAPI.checkAndParseVertexId(target); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CountAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CountAPI.java index 7dd58dd892..9ac1bf69c3 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CountAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CountAPI.java @@ -27,7 +27,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.CountTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CrosspointsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CrosspointsAPI.java index de728b57dc..2d98c4d144 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CrosspointsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CrosspointsAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT; @@ -25,7 +27,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.PathsTraverser; @@ -78,7 +80,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id sourceId = VertexAPI.checkAndParseVertexId(source); Id targetId = VertexAPI.checkAndParseVertexId(target); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); PathsTraverser traverser = new PathsTraverser(g); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedCrosspointsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedCrosspointsAPI.java index 6307ad332c..e9c5028da2 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedCrosspointsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedCrosspointsAPI.java @@ -31,7 +31,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedPathsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedPathsAPI.java index 4f3a783a3b..383fec6e5c 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedPathsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/CustomizedPathsAPI.java @@ -32,7 +32,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.CustomizePathsTraverser; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgeExistenceAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgeExistenceAPI.java index 388f40e6ef..154d031008 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgeExistenceAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgeExistenceAPI.java @@ -23,7 +23,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.EdgeExistenceTraverser; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgesAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgesAPI.java index 807fcce92c..9ae331a02d 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgesAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/EdgesAPI.java @@ -25,9 +25,9 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.CompressInterceptor.Compress; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/FusiformSimilarityAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/FusiformSimilarityAPI.java index 2c0ea1ff33..6536fc22c3 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/FusiformSimilarityAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/FusiformSimilarityAPI.java @@ -27,7 +27,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.FusiformSimilarityTraverser; import org.apache.hugegraph.traversal.algorithm.FusiformSimilarityTraverser.SimilarsMap; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/JaccardSimilarityAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/JaccardSimilarityAPI.java index 59f94f23e2..f410212bb2 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/JaccardSimilarityAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/JaccardSimilarityAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_LIMIT; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -26,7 +28,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.JaccardSimilarTraverser; @@ -79,7 +81,7 @@ public String get(@Context GraphManager manager, Id sourceId = VertexAPI.checkAndParseVertexId(vertex); Id targetId = VertexAPI.checkAndParseVertexId(other); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); double similarity; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KneighborAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KneighborAPI.java index 83183d08c5..6351c03e44 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KneighborAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KneighborAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.NO_LIMIT; @@ -30,7 +32,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; @@ -104,7 +106,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id source = VertexAPI.checkAndParseVertexId(sourceV); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KoutAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KoutAPI.java index e784e38b40..38bb536e0d 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KoutAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/KoutAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -31,7 +33,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; @@ -110,7 +112,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id sourceId = VertexAPI.checkAndParseVertexId(source); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/MultiNodeShortestPathAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/MultiNodeShortestPathAPI.java index a2a7a4fd96..6b42350cf1 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/MultiNodeShortestPathAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/MultiNodeShortestPathAPI.java @@ -25,7 +25,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.MultiNodeShortestPathTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/NeighborRankAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/NeighborRankAPI.java index 08396aa0b3..c5ec47b7da 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/NeighborRankAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/NeighborRankAPI.java @@ -28,7 +28,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.NeighborRankTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PathsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PathsAPI.java index 5c3a5c5d99..b4345b1d59 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PathsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PathsAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEPTH; @@ -30,7 +32,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.CollectionPathsTraverser; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; @@ -92,7 +94,7 @@ public String get(@Context GraphManager manager, Id sourceId = VertexAPI.checkAndParseVertexId(source); Id targetId = VertexAPI.checkAndParseVertexId(target); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); PathsTraverser traverser = new PathsTraverser(g); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PersonalRankAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PersonalRankAPI.java index 45393e2a2b..5367eed10b 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PersonalRankAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/PersonalRankAPI.java @@ -26,7 +26,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.API; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RaysAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RaysAPI.java index fda3d16369..aa3b20310c 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RaysAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RaysAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT; @@ -29,7 +31,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.SubGraphTraverser; @@ -85,7 +87,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id source = VertexAPI.checkAndParseVertexId(sourceV); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ResourceAllocationAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ResourceAllocationAPI.java index d3ff2b4ae5..32b2d305f0 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ResourceAllocationAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ResourceAllocationAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -24,7 +26,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.PredictionTraverser; import org.apache.hugegraph.type.define.Directions; @@ -77,7 +79,7 @@ public String create(@Context GraphManager manager, Id targetId = VertexAPI.checkAndParseVertexId(other); E.checkArgument(!current.equals(other), "The source and target vertex id can't be same"); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); try (PredictionTraverser traverser = new PredictionTraverser(g)) { diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RingsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RingsAPI.java index 62726fd2f9..5f2c76172b 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RingsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/RingsAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT; @@ -29,7 +31,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.SubGraphTraverser; @@ -88,7 +90,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id source = VertexAPI.checkAndParseVertexId(sourceV); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SameNeighborsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SameNeighborsAPI.java index a4e652629e..c89c53c44c 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SameNeighborsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SameNeighborsAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -30,7 +32,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.SameNeighborTraverser; @@ -83,7 +85,7 @@ public String get(@Context GraphManager manager, Id sourceId = VertexAPI.checkAndParseVertexId(vertex); Id targetId = VertexAPI.checkAndParseVertexId(other); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); SameNeighborTraverser traverser = new SameNeighborTraverser(g); @@ -108,7 +110,7 @@ public String sameNeighbors(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); - Directions dir = Directions.convert(EdgeAPI.parseDirection(request.direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(request.direction)); HugeGraph g = graph(manager, graphSpace, graph); SameNeighborTraverser traverser = new SameNeighborTraverser(g); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ShortestPathAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ShortestPathAPI.java index 6a6ecd2317..16a4b26cb8 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ShortestPathAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/ShortestPathAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -28,7 +30,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.ShortestPathTraverser; @@ -103,7 +105,7 @@ public String get(@Context GraphManager manager, Id sourceId = VertexAPI.checkAndParseVertexId(source); Id targetId = VertexAPI.checkAndParseVertexId(target); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SingleSourceShortestPathAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SingleSourceShortestPathAPI.java index 85e23d9b76..50fc31b154 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SingleSourceShortestPathAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/SingleSourceShortestPathAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT; @@ -28,7 +30,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser; @@ -88,7 +90,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id sourceId = VertexAPI.checkAndParseVertexId(source); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graphSpace, graph); SingleSourceShortestPathTraverser traverser = diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/TemplatePathsAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/TemplatePathsAPI.java index d264d6b3b2..84f963baa3 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/TemplatePathsAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/TemplatePathsAPI.java @@ -27,7 +27,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.TemplatePathsTraverser; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/Vertices.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/Vertices.java index 3efee83ab2..874ab24791 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/Vertices.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/Vertices.java @@ -24,9 +24,9 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.optimize.TraversalUtil; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/VerticesAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/VerticesAPI.java index 2f853ec352..0dc09256fe 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/VerticesAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/VerticesAPI.java @@ -26,9 +26,9 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.filter.CompressInterceptor.Compress; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/WeightedShortestPathAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/WeightedShortestPathAPI.java index e705bfba09..a9bbcaf0d3 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/WeightedShortestPathAPI.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/traversers/WeightedShortestPathAPI.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.api.traversers; +import org.apache.hugegraph.util.TinkerPopUtil; + import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_MAX_DEGREE; @@ -28,7 +30,7 @@ import org.apache.hugegraph.api.API; import org.apache.hugegraph.api.graph.EdgeAPI; import org.apache.hugegraph.api.graph.VertexAPI; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; @@ -101,7 +103,7 @@ public String get(@Context GraphManager manager, ApiMeasurer measure = new ApiMeasurer(); Id sourceId = VertexAPI.checkAndParseVertexId(source); Id targetId = VertexAPI.checkAndParseVertexId(target); - Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + Directions dir = TinkerPopUtil.direction(EdgeAPI.parseDirection(direction)); E.checkArgumentNotNull(weight, "The weight property can't be null"); HugeGraph g = graph(manager, graphSpace, graph); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/ContextGremlinServer.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/ContextGremlinServer.java index e859050132..6911b20302 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/ContextGremlinServer.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/ContextGremlinServer.java @@ -21,7 +21,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.auth.HugeGraphAuthProxy.Context; import org.apache.hugegraph.auth.HugeGraphAuthProxy.ContextThreadPoolExecutor; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeAuthenticator.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeAuthenticator.java index 243342b63f..e58a7eb5a9 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeAuthenticator.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeAuthenticator.java @@ -22,16 +22,16 @@ import java.util.Map; import java.util.regex.Pattern; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.auth.HugeGraphAuthProxy.Context; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.OptionSpace; import org.apache.hugegraph.config.ServerOptions; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.type.Nameable; +import org.apache.hugegraph.type.Namifiable; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.JsonUtil; import org.apache.tinkerpop.gremlin.groovy.jsr223.dsl.credential.CredentialGraphTokens; @@ -477,12 +477,12 @@ private boolean matchResource(HugePermission requiredAction, // check label String requiredLabel; if (requiredType.isSchema()) { - requiredLabel = ((Nameable) requiredResource.operated()).name(); + requiredLabel = ((Namifiable) requiredResource.operated()).name(); } else if (requiredType.isGraph()) { if (requiredResource.operated() instanceof HugeElement) { requiredLabel = ((HugeElement) requiredResource.operated()).label(); } else { - requiredLabel = ((Nameable) requiredResource.operated()).name(); + requiredLabel = ((Namifiable) requiredResource.operated()).name(); } } else { return true; @@ -651,7 +651,7 @@ public static RequiredPerm fromJson(String json) { } public ResourceObject resourceObject() { - Nameable elem = HugeResource.NameObject.ANY; + Namifiable elem = HugeResource.NameObject.ANY; return ResourceObject.of(this.graphSpace, this.owner, this.resource, elem); } } diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java index bb954446db..78ef3d72d2 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeFactoryAuthProxy.java @@ -27,7 +27,7 @@ import java.util.Set; import org.apache.commons.configuration2.Configuration; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; @@ -38,7 +38,7 @@ import org.apache.hugegraph.backend.tx.IndexableTransaction; import org.apache.hugegraph.concurrent.LockManager; import org.apache.hugegraph.metrics.ServerReporter; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.schema.builder.AbstractBuilder; import org.apache.hugegraph.schema.builder.EdgeLabelBuilder; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java index 9ecda6b9f7..702abfe3b5 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java @@ -41,14 +41,15 @@ import org.apache.commons.configuration2.Configuration; import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.auth.HugeAuthenticator.RolePerm; import org.apache.hugegraph.auth.HugeAuthenticator.User; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CacheManager; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendFeatures; import org.apache.hugegraph.backend.store.BackendStoreInfo; import org.apache.hugegraph.backend.store.BackendStoreProvider; @@ -63,13 +64,13 @@ import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.rpc.RpcServiceConfig4Client; import org.apache.hugegraph.rpc.RpcServiceConfig4Server; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.structure.HugeFeatures; @@ -81,7 +82,7 @@ import org.apache.hugegraph.task.TaskStatus; import org.apache.hugegraph.traversal.optimize.HugeScriptTraversal; import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.Nameable; +import org.apache.hugegraph.type.Namifiable; import org.apache.hugegraph.type.define.GraphMode; import org.apache.hugegraph.type.define.GraphReadMode; import org.apache.hugegraph.util.E; @@ -743,7 +744,7 @@ public void proxy(HugeGraph graph) { } @Override - public boolean sameAs(HugeGraph graph) { + public boolean sameAs(HugeGraphSupplier graph) { if (graph instanceof HugeGraphAuthProxy) { graph = ((HugeGraphAuthProxy) graph).hugegraph; } @@ -1053,7 +1054,7 @@ private void verifyPermission(HugePermission actionPerm, LOG.debug("Using requestGraphSpace: {}", graphSpace); } - Nameable elem = HugeResource.NameObject.ANY; + Namifiable elem = HugeResource.NameObject.ANY; return ResourceObject.of(graphSpace, graph, resType, elem); }); } @@ -1147,7 +1148,7 @@ private void verifyNamePermission(HugePermission actionPerm, ResourceType resType, String name) { verifyResPermission(actionPerm, true, () -> { String graph = this.hugegraph.name(); - Nameable elem = HugeResource.NameObject.of(name); + Namifiable elem = HugeResource.NameObject.of(name); // For global resources like USER_GROUP, use request graph space from HugeGraphAuthProxy // instead of the graph space where authManager is located @@ -1513,7 +1514,7 @@ private HugeTask verifyTaskPermission(HugePermission actionPerm, Object r = verifyResPermission(actionPerm, throwIfNoPerm, () -> { String graph = HugeGraphAuthProxy.this.hugegraph.name(); String name = task.id().toString(); - Nameable elem = HugeResource.NameObject.of(name); + Namifiable elem = HugeResource.NameObject.of(name); return ResourceObject.of(graphSpace(), graph, ResourceType.TASK, elem); }, () -> { return hasTaskPermission(task); diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/core/GraphManager.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/core/GraphManager.java index 62b588c911..1a8c1b5d1e 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/core/GraphManager.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/core/GraphManager.java @@ -48,7 +48,7 @@ import org.apache.commons.configuration2.MapConfiguration; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; @@ -59,7 +59,7 @@ import org.apache.hugegraph.auth.HugeGraphAuthProxy; import org.apache.hugegraph.auth.HugeUser; import org.apache.hugegraph.auth.StandardAuthenticator; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CacheManager; import org.apache.hugegraph.backend.store.AbstractBackendStoreProvider; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/kvstore/KvStoreImpl.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/kvstore/KvStoreImpl.java index 01f217d63b..c6c7f6eae2 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/kvstore/KvStoreImpl.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/kvstore/KvStoreImpl.java @@ -25,9 +25,9 @@ import java.util.Map; import java.util.Optional; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.variables.HugeVariables; import org.apache.tinkerpop.gremlin.structure.Vertex; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/JsonSerializer.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/JsonSerializer.java index 8d02dd6c8c..e7b5952d2d 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/JsonSerializer.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/JsonSerializer.java @@ -24,17 +24,17 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.api.API; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.iterator.Metadatable; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.space.GraphSpace; import org.apache.hugegraph.space.SchemaTemplate; import org.apache.hugegraph.space.Service; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/Serializer.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/Serializer.java index 1585725b09..ddc2102f60 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/Serializer.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/serializer/Serializer.java @@ -23,12 +23,12 @@ import java.util.Map; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.space.GraphSpace; import org.apache.hugegraph.space.SchemaTemplate; import org.apache.hugegraph.space.Service; diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/server/ApplicationConfig.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/server/ApplicationConfig.java index dd4a0f46e9..9bbed7f486 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/server/ApplicationConfig.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/server/ApplicationConfig.java @@ -17,11 +17,11 @@ package org.apache.hugegraph.server; -import org.apache.hugegraph.HugeException; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.define.WorkLoad; import org.apache.hugegraph.event.EventHub; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.util.E; import org.apache.hugegraph.version.CoreVersion; import org.apache.tinkerpop.gremlin.server.util.MetricManager; diff --git a/hugegraph-server/hugegraph-core/pom.xml b/hugegraph-server/hugegraph-core/pom.xml index 70b7a125af..88d89f6898 100644 --- a/hugegraph-server/hugegraph-core/pom.xml +++ b/hugegraph-server/hugegraph-core/pom.xml @@ -32,13 +32,6 @@ 0.7.4 5.12.1 1.8.1 - 1.10.0 - 2.6.2 - portable-1.8.3 - 5.1.6 - 8.11.2 - 1.0.2 - 2012_u6 1.21 11.1.0 8.5.9 @@ -206,58 +199,6 @@ ${lz4.version} - - - org.ansj - ansj_seg - ${ansj-seg.version} - - - com.hankcs - hanlp - ${hanlp.version} - - - org.apache.lucene - lucene-analyzers-smartcn - ${lucene.version} - - - org.apache.lucene - lucene-core - ${lucene.version} - - - com.huaban - jieba-analysis - ${jieba-analysis.version} - - - org.lionsoul - jcseg-core - ${jcseg.version} - - - com.chenlb.mmseg4j - mmseg4j-core - ${mmseg4j-core.version} - - - com.janeluo - ikanalyzer - ${ikanalyzer.version} - - - org.apache.lucene - lucene-core - - - org.apache.lucene - lucene-analyzers-common - - - - it.unimi.dsi @@ -295,7 +236,7 @@ org.apache.hugegraph - hg-store-common + hugegraph-struct ${revision} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeException.java deleted file mode 100644 index fec7bc1449..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeException.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph; - -import java.io.InterruptedIOException; - -import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException; - -public class HugeException extends RuntimeException { - - private static final long serialVersionUID = -8711375282196157058L; - - public HugeException(String message) { - super(message); - } - - public HugeException(String message, Throwable cause) { - super(message, cause); - } - - public HugeException(String message, Object... args) { - super(String.format(message, args)); - } - - public HugeException(String message, Throwable cause, Object... args) { - super(String.format(message, args), cause); - } - - public Throwable rootCause() { - return rootCause(this); - } - - public static Throwable rootCause(Throwable e) { - Throwable cause = e; - while (cause.getCause() != null) { - cause = cause.getCause(); - } - return cause; - } - - public static boolean isInterrupted(Throwable e) { - Throwable rootCause = HugeException.rootCause(e); - return rootCause instanceof InterruptedException || - rootCause instanceof TraversalInterruptedException || - rootCause instanceof InterruptedIOException; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeFactory.java index f258cb5c7b..cac015b0f6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeFactory.java @@ -17,6 +17,8 @@ package org.apache.hugegraph; +import org.apache.hugegraph.exception.HugeException; + import java.io.File; import java.net.URL; import java.util.HashMap; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java index 927614488e..6cc903a64d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java @@ -27,8 +27,8 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.hugegraph.auth.AuthManager; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendFeatures; import org.apache.hugegraph.backend.store.BackendStoreInfo; import org.apache.hugegraph.backend.store.BackendStoreProvider; @@ -39,13 +39,13 @@ import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.rpc.RpcServiceConfig4Client; import org.apache.hugegraph.rpc.RpcServiceConfig4Server; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeFeatures; import org.apache.hugegraph.task.TaskScheduler; import org.apache.hugegraph.traversal.optimize.HugeConnectiveLabelStepStrategy; @@ -70,7 +70,7 @@ /** * Graph interface for Gremlin operations */ -public interface HugeGraph extends Graph { +public interface HugeGraph extends Graph, HugeGraphSupplier { HugeGraph hugegraph(); @@ -280,7 +280,7 @@ public interface HugeGraph extends Graph { void proxy(HugeGraph graph); - boolean sameAs(HugeGraph graph); + boolean sameAs(HugeGraphSupplier graph); long now(); @@ -307,15 +307,6 @@ default List mapVlId2Name(Collection ids) { return names; } - default List mapElId2Name(Collection ids) { - List names = new ArrayList<>(ids.size()); - for (Id id : ids) { - SchemaElement schema = this.edgeLabel(id); - names.add(schema.name()); - } - return names; - } - default List mapIlId2Name(Collection ids) { List names = new ArrayList<>(ids.size()); for (Id id : ids) { @@ -347,16 +338,6 @@ default Id[] mapElName2Id(String[] edgeLabels) { return ids; } - default Set> mapPairId2Name( - Set> pairs) { - Set> results = new HashSet<>(pairs.size()); - for (Pair pair : pairs) { - results.add(Pair.of(this.vertexLabel(pair.getLeft()).name(), - this.vertexLabel(pair.getRight()).name())); - } - return results; - } - default Id[] mapVlName2Id(String[] vertexLabels) { Id[] ids = new Id[vertexLabels.length]; for (int i = 0; i < vertexLabels.length; i++) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java index 7f79c93bb7..b55ad34e19 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java @@ -17,6 +17,8 @@ package org.apache.hugegraph; +import org.apache.hugegraph.exception.HugeException; + import java.util.Arrays; import java.util.Collection; import java.util.Date; @@ -34,7 +36,7 @@ import org.apache.hugegraph.auth.AuthManager; import org.apache.hugegraph.auth.StandardAuthManager; import org.apache.hugegraph.auth.StandardAuthManagerV2; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.LocalCounter; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CacheNotifier; @@ -43,12 +45,12 @@ import org.apache.hugegraph.backend.cache.CachedGraphTransaction; import org.apache.hugegraph.backend.cache.CachedSchemaTransaction; import org.apache.hugegraph.backend.cache.CachedSchemaTransactionV2; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.id.SnowflakeIdGenerator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.AbstractSerializer; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.serializer.SerializerFactory; import org.apache.hugegraph.backend.store.BackendFeatures; import org.apache.hugegraph.backend.store.BackendProviderFactory; @@ -76,13 +78,13 @@ import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.rpc.RpcServiceConfig4Client; import org.apache.hugegraph.rpc.RpcServiceConfig4Server; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeFeatures; @@ -1255,7 +1257,7 @@ public final void proxy(HugeGraph graph) { } @Override - public boolean sameAs(HugeGraph graph) { + public boolean sameAs(HugeGraphSupplier graph) { return this == graph; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java deleted file mode 100644 index 8e7537e072..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.util.Set; - -public interface Analyzer { - - Set segment(String text); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java deleted file mode 100644 index 21dd157b11..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.serializer.SerializerFactory; - -public class AnalyzerFactory { - - private static final Map> ANALYZERS; - - static { - ANALYZERS = new ConcurrentHashMap<>(); - } - - public static Analyzer analyzer(String name, String mode) { - name = name.toLowerCase(); - switch (name) { - case "ansj": - return new AnsjAnalyzer(mode); - case "hanlp": - return new HanLPAnalyzer(mode); - case "smartcn": - return new SmartCNAnalyzer(mode); - case "jieba": - return new JiebaAnalyzer(mode); - case "jcseg": - return new JcsegAnalyzer(mode); - case "mmseg4j": - return new MMSeg4JAnalyzer(mode); - case "ikanalyzer": - return new IKAnalyzer(mode); - default: - return customizedAnalyzer(name, mode); - } - } - - private static Analyzer customizedAnalyzer(String name, String mode) { - Class clazz = ANALYZERS.get(name); - if (clazz == null) { - throw new HugeException("Not exists analyzer: %s", name); - } - - assert Analyzer.class.isAssignableFrom(clazz); - try { - return clazz.getConstructor(String.class).newInstance(mode); - } catch (Exception e) { - throw new HugeException( - "Failed to construct analyzer '%s' with mode '%s'", - e, name, mode); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void register(String name, String classPath) { - ClassLoader classLoader = SerializerFactory.class.getClassLoader(); - Class clazz; - try { - clazz = classLoader.loadClass(classPath); - } catch (Exception e) { - throw new HugeException("Load class path '%s' failed", - e, classPath); - } - - // Check subclass - if (!Analyzer.class.isAssignableFrom(clazz)) { - throw new HugeException("Class '%s' is not a subclass of " + - "class Analyzer", classPath); - } - - // Check exists - if (ANALYZERS.containsKey(name)) { - throw new HugeException("Exists analyzer: %s(%s)", - name, ANALYZERS.get(name).getName()); - } - - // Register class - ANALYZERS.put(name, (Class) clazz); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java deleted file mode 100644 index 2f857cd171..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.util.List; -import java.util.Set; - -import org.ansj.domain.Result; -import org.ansj.domain.Term; -import org.ansj.splitWord.analysis.BaseAnalysis; -import org.ansj.splitWord.analysis.IndexAnalysis; -import org.ansj.splitWord.analysis.NlpAnalysis; -import org.ansj.splitWord.analysis.ToAnalysis; -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; - -import com.google.common.collect.ImmutableList; - -/** - * Reference from https://github.com/NLPchina/ansj_seg/wiki - */ -public class AnsjAnalyzer implements Analyzer { - - public static final List SUPPORT_MODES = ImmutableList.of( - "BaseAnalysis", - "IndexAnalysis", - "ToAnalysis", - "NlpAnalysis" - ); - - private final String analysis; - - public AnsjAnalyzer(String mode) { - if (!SUPPORT_MODES.contains(mode)) { - throw new ConfigException( - "Unsupported segment mode '%s' for ansj analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); - } - this.analysis = mode; - } - - @Override - public Set segment(String text) { - Result terms; - switch (this.analysis) { - case "BaseAnalysis": - terms = BaseAnalysis.parse(text); - break; - case "ToAnalysis": - terms = ToAnalysis.parse(text); - break; - case "NlpAnalysis": - terms = NlpAnalysis.parse(text); - break; - case "IndexAnalysis": - terms = IndexAnalysis.parse(text); - break; - default: - throw new AssertionError(String.format( - "Unsupported segment mode '%s'", this.analysis)); - } - - assert terms != null; - Set result = InsertionOrderUtil.newSet(); - for (Term term : terms) { - result.add(term.getName()); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java deleted file mode 100644 index 8b5fa6aa0a..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; - -import com.google.common.collect.ImmutableList; -import com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment; -import com.hankcs.hanlp.seg.NShort.NShortSegment; -import com.hankcs.hanlp.seg.Segment; -import com.hankcs.hanlp.seg.common.Term; -import com.hankcs.hanlp.tokenizer.IndexTokenizer; -import com.hankcs.hanlp.tokenizer.NLPTokenizer; -import com.hankcs.hanlp.tokenizer.SpeedTokenizer; -import com.hankcs.hanlp.tokenizer.StandardTokenizer; - -/** - * Reference from https://github.com/hankcs/HanLP/wiki - */ -public class HanLPAnalyzer implements Analyzer { - - public static final List SUPPORT_MODES = - ImmutableList.builder() - .add("standard") - .add("nlp") - .add("index") - .add("nShort") - .add("shortest") - .add("speed") - .build(); - - private static final Segment N_SHORT_SEGMENT = - new NShortSegment().enableCustomDictionary(false) - .enablePlaceRecognize(true) - .enableOrganizationRecognize(true); - private static final Segment DIJKSTRA_SEGMENT = - new DijkstraSegment().enableCustomDictionary(false) - .enablePlaceRecognize(true) - .enableOrganizationRecognize(true); - - private final String tokenizer; - - public HanLPAnalyzer(String mode) { - if (!SUPPORT_MODES.contains(mode)) { - throw new ConfigException( - "Unsupported segment mode '%s' for hanlp analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); - } - this.tokenizer = mode; - } - - @Override - public Set segment(String text) { - List terms; - switch (this.tokenizer) { - case "standard": - terms = StandardTokenizer.segment(text); - break; - case "nlp": - terms = NLPTokenizer.segment(text); - break; - case "index": - terms = IndexTokenizer.segment(text); - break; - case "nShort": - terms = N_SHORT_SEGMENT.seg(text); - break; - case "shortest": - terms = DIJKSTRA_SEGMENT.seg(text); - break; - case "speed": - terms = SpeedTokenizer.segment(text); - break; - default: - throw new AssertionError(String.format( - "Unsupported segment mode '%s'", this.tokenizer)); - } - - assert terms != null; - Set result = InsertionOrderUtil.newSet(); - for (Term term : terms) { - result.add(term.word); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java deleted file mode 100644 index ab564f396f..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.io.StringReader; -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; -import org.wltea.analyzer.core.IKSegmenter; -import org.wltea.analyzer.core.Lexeme; - -import com.google.common.collect.ImmutableList; - -/** - * Reference from https://github.com/yyn0210/IKAnalyzer - */ -public class IKAnalyzer implements Analyzer { - - public static final List SUPPORT_MODES = ImmutableList.of( - "smart", - "max_word" - ); - - private final boolean smartSegMode; - - public IKAnalyzer(String mode) { - if (!SUPPORT_MODES.contains(mode)) { - throw new ConfigException( - "Unsupported segment mode '%s' for ikanalyzer, " + - "the available values are %s", mode, SUPPORT_MODES); - } - this.smartSegMode = SUPPORT_MODES.get(0).equals(mode); - } - - @Override - public Set segment(String text) { - Set result = InsertionOrderUtil.newSet(); - IKSegmenter ik = new IKSegmenter(new StringReader(text), - this.smartSegMode); - try { - Lexeme word; - while ((word = ik.next()) != null) { - result.add(word.getLexemeText()); - } - } catch (Exception e) { - throw new HugeException("IKAnalyzer segment text '%s' failed", - e, text); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java deleted file mode 100644 index 3740e87b19..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.io.StringReader; -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; -import org.lionsoul.jcseg.ISegment; -import org.lionsoul.jcseg.IWord; -import org.lionsoul.jcseg.dic.ADictionary; -import org.lionsoul.jcseg.dic.DictionaryFactory; -import org.lionsoul.jcseg.segmenter.SegmenterConfig; - -import com.google.common.collect.ImmutableList; - -/** - * Reference from https://github.com/lionsoul2014/jcseg - */ -public class JcsegAnalyzer implements Analyzer { - - public static final List SUPPORT_MODES = ImmutableList.of( - "Simple", - "Complex" - ); - - private static final SegmenterConfig CONFIG = new SegmenterConfig(); - private static final ADictionary DIC = DictionaryFactory.createDefaultDictionary(CONFIG); - - private final ISegment.Type type; - - public JcsegAnalyzer(String mode) { - if (!SUPPORT_MODES.contains(mode)) { - throw new ConfigException( - "Unsupported segment mode '%s' for jcseg analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); - } - - if ("Simple".equals(mode)) { - this.type = ISegment.SIMPLE; - } else { - this.type = ISegment.COMPLEX; - } - } - - @Override - public Set segment(String text) { - Set result = InsertionOrderUtil.newSet(); - try { - ISegment segmentor = this.type.factory.create(CONFIG, DIC); - segmentor.reset(new StringReader(text)); - - IWord word; - while ((word = segmentor.next()) != null) { - result.add(word.getValue()); - } - } catch (Exception e) { - throw new HugeException("Jcseg segment text '%s' failed", e, text); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java deleted file mode 100644 index 7c280a50a1..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; - -import com.google.common.collect.ImmutableList; -import com.huaban.analysis.jieba.JiebaSegmenter; -import com.huaban.analysis.jieba.SegToken; - -/** - * Reference from https://github.com/huaban/jieba-analysis - */ -public class JiebaAnalyzer implements Analyzer { - - public static final List SUPPORT_MODES = ImmutableList.of( - "SEARCH", - "INDEX" - ); - - private static final JiebaSegmenter JIEBA_SEGMENTER = new JiebaSegmenter(); - - private final JiebaSegmenter.SegMode segMode; - - public JiebaAnalyzer(String mode) { - if (!SUPPORT_MODES.contains(mode)) { - throw new ConfigException( - "Unsupported segment mode '%s' for jieba analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); - } - this.segMode = JiebaSegmenter.SegMode.valueOf(mode); - } - - @Override - public Set segment(String text) { - Set result = InsertionOrderUtil.newSet(); - for (SegToken token : JIEBA_SEGMENTER.process(text, this.segMode)) { - result.add(token.word); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java deleted file mode 100644 index 26e937a538..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.io.StringReader; -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; - -import com.chenlb.mmseg4j.ComplexSeg; -import com.chenlb.mmseg4j.Dictionary; -import com.chenlb.mmseg4j.MMSeg; -import com.chenlb.mmseg4j.MaxWordSeg; -import com.chenlb.mmseg4j.Seg; -import com.chenlb.mmseg4j.SimpleSeg; -import com.chenlb.mmseg4j.Word; -import com.google.common.collect.ImmutableList; - -/** - * Reference from https://github.com/chenlb/mmseg4j-core - */ -public class MMSeg4JAnalyzer implements Analyzer { - - public static final List SUPPORT_MODES = ImmutableList.of( - "Simple", - "Complex", - "MaxWord" - ); - - private static final Dictionary DIC = Dictionary.getInstance(); - - private final Seg seg; - - public MMSeg4JAnalyzer(String mode) { - if (!SUPPORT_MODES.contains(mode)) { - throw new ConfigException( - "Unsupported segment mode '%s' for mmseg4j analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); - } - int index = SUPPORT_MODES.indexOf(mode); - switch (index) { - case 0: - this.seg = new SimpleSeg(DIC); - break; - case 1: - this.seg = new ComplexSeg(DIC); - break; - case 2: - this.seg = new MaxWordSeg(DIC); - break; - default: - throw new AssertionError(String.format( - "Unsupported segment mode '%s'", mode)); - } - } - - @Override - public Set segment(String text) { - Set result = InsertionOrderUtil.newSet(); - MMSeg mmSeg = new MMSeg(new StringReader(text), this.seg); - try { - Word word; - while ((word = mmSeg.next()) != null) { - result.add(word.getString()); - } - } catch (Exception e) { - throw new HugeException("MMSeg4j segment text '%s' failed", - e, text); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java deleted file mode 100644 index f265ade214..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.analyzer; - -import java.io.Reader; -import java.io.StringReader; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.util.InsertionOrderUtil; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer; -import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; - -/** - * Reference from https://lucene.apache.org/core/8_11_2/analyzers-smartcn/index.html - */ -public class SmartCNAnalyzer implements Analyzer { - - private static final SmartChineseAnalyzer ANALYZER = - new SmartChineseAnalyzer(); - - public SmartCNAnalyzer(String mode) { - // pass - } - - @Override - public Set segment(String text) { - Set result = InsertionOrderUtil.newSet(); - Reader reader = new StringReader(text); - try (TokenStream tokenStream = ANALYZER.tokenStream("text", reader)) { - tokenStream.reset(); - CharTermAttribute term; - while (tokenStream.incrementToken()) { - term = tokenStream.getAttribute(CharTermAttribute.class); - result.add(term.toString()); - } - } catch (Exception e) { - throw new HugeException("SmartCN segment text '%s' failed", - e, text); - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java index d1c8887238..09b08f3a00 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java @@ -25,7 +25,7 @@ import javax.security.sasl.AuthenticationException; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; public interface AuthManager { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/EntityManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/EntityManager.java index 4633625729..2a0b21ee62 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/EntityManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/EntityManager.java @@ -22,19 +22,19 @@ import java.util.Map; import java.util.function.Function; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Entity; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.iterator.MapperIterator; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeAccess.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeAccess.java index c40b67d57d..eef86c27b4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeAccess.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeAccess.java @@ -27,9 +27,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Relationship; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.type.define.DataType; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Edge; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeBelong.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeBelong.java index 7d668f3c19..4d0353aec7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeBelong.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeBelong.java @@ -24,9 +24,9 @@ import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Relationship; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; import org.apache.tinkerpop.gremlin.structure.T; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeGroup.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeGroup.java index defe5d130f..8e5ee9759e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeGroup.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeGroup.java @@ -25,9 +25,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Entity; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; import org.apache.tinkerpop.gremlin.structure.T; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeProject.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeProject.java index faafcddded..9b024bc57b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeProject.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeProject.java @@ -27,9 +27,9 @@ import org.apache.commons.lang.StringUtils; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Entity; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeResource.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeResource.java index 74577c258e..7dbd152d4e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeResource.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeResource.java @@ -27,12 +27,12 @@ import java.util.Objects; import java.util.Set; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.traversal.optimize.TraversalUtil; -import org.apache.hugegraph.type.Nameable; -import org.apache.hugegraph.type.Typeable; +import org.apache.hugegraph.type.Namifiable; +import org.apache.hugegraph.type.Typifiable; import org.apache.hugegraph.util.JsonUtil; import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; import org.apache.tinkerpop.gremlin.structure.Property; @@ -160,7 +160,7 @@ public boolean filter(ResourceObject resourceObject) { return this.filter((AuthElement) resourceObject.operated()); } if (resType.isSchema() || CHECK_NAME_RESS.contains(resType)) { - return this.filter((Nameable) resourceObject.operated()); + return this.filter((Namifiable) resourceObject.operated()); } } @@ -173,15 +173,15 @@ public boolean filter(ResourceObject resourceObject) { private boolean filter(AuthElement element) { assert this.type.match(element.type()); - if (element instanceof Nameable) { - return this.filter((Nameable) element); + if (element instanceof Namifiable) { + return this.filter((Namifiable) element); } return true; } - private boolean filter(Nameable element) { - assert !(element instanceof Typeable) || this.type.match( - ResourceType.from(((Typeable) element).type())); + private boolean filter(Namifiable element) { + assert !(element instanceof Typifiable) || this.type.match( + ResourceType.from(((Typifiable) element).type())); return this.matchLabel(element.name()); } @@ -288,7 +288,7 @@ public String toString() { public static boolean allowed(ResourceObject resourceObject) { // Allowed to access system(hidden) schema by anyone if (resourceObject.type().isSchema()) { - Nameable schema = (Nameable) resourceObject.operated(); + Namifiable schema = (Namifiable) resourceObject.operated(); return Hidden.isHidden(schema.name()); } @@ -302,7 +302,7 @@ public static HugeResource parseResource(String resource) { public boolean matchProperties(HugeResource other) { return matchProperties(other.properties); } - public static class NameObject implements Nameable { + public static class NameObject implements Namifiable { public static final NameObject ANY = new NameObject("*"); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeRole.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeRole.java index ee5955bbaf..78d1ff1197 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeRole.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeRole.java @@ -25,9 +25,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Entity; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; import org.apache.tinkerpop.gremlin.structure.T; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeTarget.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeTarget.java index 34ff5aa87d..70fbb2803e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeTarget.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeTarget.java @@ -23,12 +23,12 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Entity; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.JsonUtil; import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeUser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeUser.java index 8a90de0b17..c12946e7eb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeUser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/HugeUser.java @@ -25,9 +25,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Entity; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; import org.apache.tinkerpop.gremlin.structure.T; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/RelationshipManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/RelationshipManager.java index a1c440611e..fa7fd1299e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/RelationshipManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/RelationshipManager.java @@ -22,20 +22,20 @@ import java.util.Map; import java.util.function.Function; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.Relationship; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.iterator.MapperIterator; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/ResourceObject.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/ResourceObject.java index b745e07fe7..1bbf66d9b4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/ResourceObject.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/ResourceObject.java @@ -18,9 +18,9 @@ package org.apache.hugegraph.auth; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.type.Nameable; +import org.apache.hugegraph.type.Namifiable; import org.apache.hugegraph.util.E; public class ResourceObject { @@ -90,12 +90,12 @@ public static ResourceObject of(String graph, } public static ResourceObject of(String graphSpace, String graph, - ResourceType type, Nameable elem) { + ResourceType type, Namifiable elem) { return new ResourceObject<>(graphSpace, graph, type, elem); } public static ResourceObject of(String graph, ResourceType type, - Nameable elem) { + Namifiable elem) { return of("DEFAULT", graph, type, elem); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/SchemaDefine.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/SchemaDefine.java index fe3556a59e..b5ea7331c7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/SchemaDefine.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/SchemaDefine.java @@ -26,15 +26,15 @@ import java.util.Locale; import java.util.Map; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.HugeTarget.P; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; @@ -298,9 +298,9 @@ protected Object[] asArray(List list) { protected abstract Object[] asArray(); } - // NOTE: travis-ci fails if class Entity implements Nameable + // NOTE: travis-ci fails if class Entity implements Namifiable public abstract static class Entity extends AuthElement - implements org.apache.hugegraph.type.Nameable { + implements org.apache.hugegraph.type.Namifiable { private static final long serialVersionUID = 4113319546914811762L; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java index 02f5e9b385..cc677ec7b1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java @@ -31,14 +31,14 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.HugeUser.P; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CacheManager; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.AuthOptions; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.type.define.Directions; @@ -109,7 +109,7 @@ public StandardAuthManager(HugeGraphParams graph) { this.access = new RelationshipManager<>(this.graph, HugeAccess.P.ACCESS, HugeAccess::fromEdge); - this.tokenGenerator = new TokenGenerator(config); + this.tokenGenerator = new TokenGenerator(config.get(AuthOptions.AUTH_TOKEN_SECRET)); LOG.info("Randomly generate a JWT secret key now"); this.ipWhiteList = new HashSet<>(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2.java index 60e17f2b33..be019260bf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2.java @@ -35,13 +35,13 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.auth.SchemaDefine.AuthElement; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CacheManager; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.AuthOptions; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.meta.MetaManager; @@ -159,7 +159,7 @@ public StandardAuthManagerV2(HugeGraphParams graph) { this.pwdCache = this.cache("users_pwd", capacity, expired); this.tokenCache = this.cache("token", capacity, expired); - this.tokenGenerator = new TokenGenerator(config); + this.tokenGenerator = new TokenGenerator(config.get(AuthOptions.AUTH_TOKEN_SECRET)); LOG.info("Randomly generate a JWT secret key now"); this.ipWhiteList = new HashSet<>(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/UserWithRole.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/UserWithRole.java index a32517bfd5..8b822056a2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/UserWithRole.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/UserWithRole.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.auth; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; public class UserWithRole { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/BackendException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/BackendException.java deleted file mode 100644 index a1f587866e..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/BackendException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend; - -import org.apache.hugegraph.HugeException; - -public class BackendException extends HugeException { - - private static final long serialVersionUID = -1947589125372576298L; - - public BackendException(String message) { - super(message); - } - - public BackendException(String message, Throwable cause) { - super(message, cause); - } - - public BackendException(String message, Object... args) { - super(message, args); - } - - public BackendException(String message, Throwable cause, Object... args) { - super(message, cause, args); - } - - public BackendException(Throwable cause) { - this("Exception in backend", cause); - } - - public static final void check(boolean expression, String message, Object... args) - throws BackendException { - if (!expression) { - throw new BackendException(message, args); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/LocalCounter.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/LocalCounter.java index 148703c072..6a166c7fbe 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/LocalCounter.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/LocalCounter.java @@ -21,8 +21,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.type.HugeType; public class LocalCounter { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/Transaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/Transaction.java index 1c7e18424d..4d93eb49be 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/Transaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/Transaction.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.backend; +import org.apache.hugegraph.exception.BackendException; + public interface Transaction { void commit() throws BackendException; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheManager.java index 30bffab814..67791483ff 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheManager.java @@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheNotifier.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheNotifier.java index e470f1067a..947ad1100e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheNotifier.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CacheNotifier.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.backend.cache; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.type.HugeType; public interface CacheNotifier extends AutoCloseable { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java index 3cc88bbf71..4a90745454 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java @@ -22,10 +22,10 @@ import java.util.function.Function; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendFeatures; import org.apache.hugegraph.backend.store.BackendMutation; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java index a6085d32c4..e8e579e15e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedGraphTransaction.java @@ -29,9 +29,9 @@ import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.backend.cache.CachedBackendStore.QueryId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryBatch; import org.apache.hugegraph.backend.query.QueryResultContext; import org.apache.hugegraph.backend.query.QueryResults; @@ -48,7 +48,7 @@ import org.apache.hugegraph.iterator.ExtendableIterator; import org.apache.hugegraph.iterator.ListIterator; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransaction.java index d393be7461..8e48218e30 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransaction.java @@ -25,8 +25,8 @@ import java.util.function.Consumer; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.backend.store.ram.IntObjectMap; import org.apache.hugegraph.backend.tx.SchemaTransaction; @@ -34,7 +34,7 @@ import org.apache.hugegraph.event.EventHub; import org.apache.hugegraph.event.EventListener; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Events; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransactionV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransactionV2.java index 74986b2e99..6ce6ae7db9 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransactionV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedSchemaTransactionV2.java @@ -27,8 +27,8 @@ import java.util.function.Consumer; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.ram.IntObjectMap; import org.apache.hugegraph.backend.tx.SchemaTransactionV2; import org.apache.hugegraph.config.CoreOptions; @@ -38,7 +38,7 @@ import org.apache.hugegraph.meta.MetaManager; import org.apache.hugegraph.meta.MetaManager.SchemaCacheClearEvent; import org.apache.hugegraph.perf.PerfUtil; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Events; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/LevelCache.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/LevelCache.java index 7f3e971314..d0ee73fa73 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/LevelCache.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/LevelCache.java @@ -20,7 +20,7 @@ import java.util.Iterator; import java.util.function.Consumer; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.ExtendableIterator; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/OffheapCache.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/OffheapCache.java index 7ed4efcd66..fde018e183 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/OffheapCache.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/OffheapCache.java @@ -24,15 +24,15 @@ import java.util.List; import java.util.function.Consumer; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.serializer.AbstractSerializer; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.backend.serializer.BinarySerializer; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/RamCache.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/RamCache.java index a5e8d162a8..b3364359dd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/RamCache.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/RamCache.java @@ -25,7 +25,7 @@ import java.util.concurrent.locks.Lock; import java.util.function.Consumer; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.concurrent.KeyLock; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java deleted file mode 100644 index 14116d8575..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.id; - -import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.structure.HugeVertex; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.Directions; -import org.apache.hugegraph.type.define.HugeKeys; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.StringEncoding; - -/** - * Class used to format and parse id of edge, the edge id consists of: - * EdgeId = { source-vertex-id > direction > parentEdgeLabelId > subEdgeLabelId - * > sortKeys > target-vertex-id } - * NOTE: - *

1. for edges with edgeLabelType = NORMAL: edgeLabelId = parentEdgeLabelId = subEdgeLabelId; - * for edges with edgeLabelType = PARENT: edgeLabelId = subEdgeLabelId, parentEdgeLabelId = - * edgeLabelId.fatherId - *

2.if we use `entry.type()` which is IN or OUT as a part of id, - * an edge's id will be different due to different directions (belongs - * to 2 owner vertex) - */ -public class EdgeId implements Id { - - public static final HugeKeys[] KEYS = new HugeKeys[]{ - HugeKeys.OWNER_VERTEX, - HugeKeys.DIRECTION, - HugeKeys.LABEL, - HugeKeys.SUB_LABEL, - HugeKeys.SORT_VALUES, - HugeKeys.OTHER_VERTEX - }; - - protected final Id ownerVertexId; - protected final Id edgeLabelId; - protected final Id subLabelId; - protected final Id otherVertexId; - protected final Directions direction; - protected final boolean directed; - protected String sortValues; - protected String cache; - - public EdgeId(HugeVertex ownerVertex, Directions direction, - Id edgeLabelId, Id subLabelId, String sortValues, HugeVertex otherVertex) { - this(ownerVertex.id(), direction, edgeLabelId, subLabelId, - sortValues, otherVertex.id()); - } - - public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, Id subLabelId, - String sortValues, Id otherVertexId) { - this(ownerVertexId, direction, edgeLabelId, subLabelId, - sortValues, otherVertexId, false); - } - - public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, Id subLabelId, - String sortValues, Id otherVertexId, boolean directed) { - this.ownerVertexId = ownerVertexId; - this.direction = direction; - this.edgeLabelId = edgeLabelId; - this.subLabelId = subLabelId; - this.sortValues = sortValues; - this.otherVertexId = otherVertexId; - this.directed = directed; - this.cache = null; - } - - @Watched - public EdgeId switchDirection() { - Directions direction = this.direction.opposite(); - return new EdgeId(this.otherVertexId, direction, this.edgeLabelId, this.subLabelId, - this.sortValues, this.ownerVertexId, this.directed); - } - - public EdgeId directed(boolean directed) { - return new EdgeId(this.ownerVertexId, this.direction, this.edgeLabelId, this.subLabelId, - this.sortValues, this.otherVertexId, directed); - } - - private Id sourceVertexId() { - return this.direction == Directions.OUT ? - this.ownerVertexId : - this.otherVertexId; - } - - private Id targetVertexId() { - return this.direction == Directions.OUT ? - this.otherVertexId : - this.ownerVertexId; - } - - public Id ownerVertexId() { - return this.ownerVertexId; - } - - public Id edgeLabelId() { - return this.edgeLabelId; - } - - public Id subLabelId() { - return this.subLabelId; - } - - public Directions direction() { - return this.direction; - } - - public byte directionCode() { - return directionToCode(this.direction); - } - - public String sortValues() { - return this.sortValues; - } - - public Id otherVertexId() { - return this.otherVertexId; - } - - @Override - public Object asObject() { - return this.asString(); - } - - @Override - public String asString() { - if (this.cache != null) { - return this.cache; - } - if (this.directed) { - this.cache = SplicingIdGenerator.concat( - IdUtil.writeString(this.ownerVertexId), - this.direction.type().string(), - IdUtil.writeLong(this.edgeLabelId), - IdUtil.writeLong(this.subLabelId), - this.sortValues, - IdUtil.writeString(this.otherVertexId)); - } else { - this.cache = SplicingIdGenerator.concat( - IdUtil.writeString(this.sourceVertexId()), - IdUtil.writeLong(this.edgeLabelId), - IdUtil.writeLong(this.subLabelId), - this.sortValues, - IdUtil.writeString(this.targetVertexId())); - } - return this.cache; - } - - @Override - public long asLong() { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] asBytes() { - return StringEncoding.encode(this.asString()); - } - - @Override - public int length() { - return this.asString().length(); - } - - @Override - public IdType type() { - return IdType.EDGE; - } - - @Override - public int compareTo(Id other) { - return this.asString().compareTo(other.asString()); - } - - @Override - public int hashCode() { - if (this.directed) { - return this.ownerVertexId.hashCode() ^ - this.direction.hashCode() ^ - this.edgeLabelId.hashCode() ^ - this.subLabelId.hashCode() ^ - this.sortValues.hashCode() ^ - this.otherVertexId.hashCode(); - } else { - return this.sourceVertexId().hashCode() ^ - this.edgeLabelId.hashCode() ^ - this.subLabelId.hashCode() ^ - this.sortValues.hashCode() ^ - this.targetVertexId().hashCode(); - } - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof EdgeId)) { - return false; - } - EdgeId other = (EdgeId) object; - if (this.directed) { - return this.ownerVertexId.equals(other.ownerVertexId) && - this.direction == other.direction && - this.edgeLabelId.equals(other.edgeLabelId) && - this.subLabelId.equals(other.subLabelId) && - this.sortValues.equals(other.sortValues) && - this.otherVertexId.equals(other.otherVertexId); - } else { - return this.sourceVertexId().equals(other.sourceVertexId()) && - this.edgeLabelId.equals(other.edgeLabelId) && - this.subLabelId.equals(other.subLabelId) && - this.sortValues.equals(other.sortValues) && - this.targetVertexId().equals(other.targetVertexId()); - } - } - - @Override - public String toString() { - return this.asString(); - } - - public static byte directionToCode(Directions direction) { - return direction.type().code(); - } - - public static Directions directionFromCode(byte code) { - return Directions.convert(HugeType.fromCode(code)); - } - - public static boolean isOutDirectionFromCode(byte code) { - return code == HugeType.EDGE_OUT.code(); - } - - public static EdgeId parse(String id) throws NotFoundException { - return parse(id, false); - } - - public static EdgeId parse(String id, boolean returnNullIfError) - throws NotFoundException { - String[] idParts = SplicingIdGenerator.split(id); - if (!(idParts.length == 5 || idParts.length == 6)) { - if (returnNullIfError) { - return null; - } - throw new NotFoundException("Edge id must be formatted as 5~6 " + - "parts, but got %s parts: '%s'", - idParts.length, id); - } - try { - if (idParts.length == 5) { - Id ownerVertexId = IdUtil.readString(idParts[0]); - Id edgeLabelId = IdUtil.readLong(idParts[1]); - Id subLabelId = IdUtil.readLong(idParts[2]); - String sortValues = idParts[3]; - Id otherVertexId = IdUtil.readString(idParts[4]); - return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, subLabelId, - sortValues, otherVertexId); - } else { - assert idParts.length == 6; - Id ownerVertexId = IdUtil.readString(idParts[0]); - HugeType direction = HugeType.fromString(idParts[1]); - Id edgeLabelId = IdUtil.readLong(idParts[2]); - Id subLabelId = IdUtil.readLong(idParts[3]); - String sortValues = idParts[4]; - Id otherVertexId = IdUtil.readString(idParts[5]); - return new EdgeId(ownerVertexId, Directions.convert(direction), - edgeLabelId, subLabelId, sortValues, otherVertexId); - } - } catch (Throwable e) { - if (returnNullIfError) { - return null; - } - throw new NotFoundException("Invalid format of edge id '%s'", - e, id); - } - } - - public static Id parseStoredString(String id) { - String[] idParts = split(id); - E.checkArgument(idParts.length == 5, "Invalid id format: %s", id); - Id ownerVertexId = IdUtil.readStoredString(idParts[0]); - Id edgeLabelId = IdGenerator.ofStoredString(idParts[1], IdType.LONG); - Id subLabelId = IdGenerator.ofStoredString(idParts[2], IdType.LONG); - String sortValues = idParts[3]; - Id otherVertexId = IdUtil.readStoredString(idParts[4]); - return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, subLabelId, - sortValues, otherVertexId); - } - - public static String asStoredString(Id id) { - EdgeId eid = (EdgeId) id; - return SplicingIdGenerator.concat( - IdUtil.writeStoredString(eid.sourceVertexId()), - IdGenerator.asStoredString(eid.edgeLabelId()), - IdGenerator.asStoredString(eid.subLabelId()), - eid.sortValues(), - IdUtil.writeStoredString(eid.targetVertexId())); - } - - public static String concat(String... ids) { - return SplicingIdGenerator.concat(ids); - } - - public static String[] split(Id id) { - return EdgeId.split(id.asString()); - } - - public static String[] split(String id) { - return SplicingIdGenerator.split(id); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/Id.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/Id.java deleted file mode 100644 index 077aa43dbb..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/Id.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.id; - -import org.apache.hugegraph.util.E; - -public interface Id extends Comparable { - - int UUID_LENGTH = 16; - - Object asObject(); - - String asString(); - - long asLong(); - - byte[] asBytes(); - - int length(); - - IdType type(); - - default boolean number() { - return this.type() == IdType.LONG; - } - - default boolean uuid() { - return this.type() == IdType.UUID; - } - - default boolean string() { - return this.type() == IdType.STRING; - } - - default boolean edge() { - return this.type() == IdType.EDGE; - } - - enum IdType { - - UNKNOWN, - LONG, - UUID, - STRING, - EDGE; - - public char prefix() { - if (this == UNKNOWN) { - return 'N'; - } - return this.name().charAt(0); - } - - public static IdType valueOfPrefix(String id) { - E.checkArgument(id != null && !id.isEmpty(), "Invalid id '%s'", id); - switch (id.charAt(0)) { - case 'L': - return IdType.LONG; - case 'U': - return IdType.UUID; - case 'S': - return IdType.STRING; - case 'E': - return IdType.EDGE; - default: - return IdType.UNKNOWN; - } - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java deleted file mode 100644 index 9f1bcc56fc..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.id; - -import java.util.Objects; -import java.util.UUID; - -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.serializer.BytesBuffer; -import org.apache.hugegraph.structure.HugeVertex; -import org.apache.hugegraph.util.Bytes; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.LongEncoding; -import org.apache.hugegraph.util.NumericUtil; -import org.apache.hugegraph.util.StringEncoding; - -public abstract class IdGenerator { - - public static final Id ZERO = IdGenerator.of(0L); - - public abstract Id generate(HugeVertex vertex); - - public static Id of(String id) { - return new StringId(id); - } - - public static Id of(UUID id) { - return new UuidId(id); - } - - public static Id of(String id, boolean uuid) { - return uuid ? new UuidId(id) : new StringId(id); - } - - public static Id of(long id) { - return new LongId(id); - } - - public static Id of(Object id) { - if (id instanceof Id) { - return (Id) id; - } else if (id instanceof String) { - return of((String) id); - } else if (id instanceof Number) { - return of(((Number) id).longValue()); - } else if (id instanceof UUID) { - return of((UUID) id); - } - return new ObjectId(id); - } - - public static Id of(byte[] bytes, IdType type) { - switch (type) { - case LONG: - return new LongId(bytes); - case UUID: - return new UuidId(bytes); - case STRING: - return new StringId(bytes); - default: - throw new AssertionError("Invalid id type " + type); - } - } - - public static Id ofStoredString(String id, IdType type) { - switch (type) { - case LONG: - return of(LongEncoding.decodeSignedB64(id)); - case UUID: - byte[] bytes = StringEncoding.decodeBase64(id); - return of(bytes, IdType.UUID); - case STRING: - return of(id); - default: - throw new AssertionError("Invalid id type " + type); - } - } - - public static String asStoredString(Id id) { - switch (id.type()) { - case LONG: - return LongEncoding.encodeSignedB64(id.asLong()); - case UUID: - return StringEncoding.encodeBase64(id.asBytes()); - case STRING: - return id.asString(); - default: - throw new AssertionError("Invalid id type " + id.type()); - } - } - - public static IdType idType(Id id) { - if (id instanceof LongId) { - return IdType.LONG; - } - if (id instanceof UuidId) { - return IdType.UUID; - } - if (id instanceof StringId) { - return IdType.STRING; - } - if (id instanceof EdgeId) { - return IdType.EDGE; - } - return IdType.UNKNOWN; - } - - public static int compareType(Id id1, Id id2) { - return idType(id1).ordinal() - idType(id2).ordinal(); - } - - /****************************** id defines ******************************/ - - public static class StringId implements Id { - - protected String id; - protected byte[] bytes; - - public StringId(String id) { - E.checkArgument(id != null && !id.isEmpty(), - "The id can't be null or empty"); - this.id = id; - this.bytes = null; - } - - public StringId(byte[] bytes) { - E.checkArgument(bytes != null && bytes.length > 0, - "The id bytes can't be null or empty"); - this.bytes = bytes; - this.id = null; - } - - @Override - public IdType type() { - return IdType.STRING; - } - - @Override - public Object asObject() { - return this.asString(); - } - - @Override - public String asString() { - if (this.id == null) { - assert this.bytes != null; - this.id = StringEncoding.decode(this.bytes); - } - return this.id; - } - - @Override - public long asLong() { - return Long.parseLong(this.asString()); - } - - @Override - public byte[] asBytes() { - if (this.bytes == null) { - assert this.id != null; - this.bytes = StringEncoding.encode(this.id); - } - return this.bytes; - } - - @Override - public int length() { - return this.asString().length(); - } - - @Override - public int compareTo(Id other) { - int cmp = compareType(this, other); - if (cmp != 0) { - return cmp; - } - if (this.id != null) { - return this.id.compareTo(other.asString()); - } else { - return Bytes.compare(this.bytes, other.asBytes()); - } - } - - @Override - public int hashCode() { - return this.asString().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof StringId)) { - return false; - } - StringId other = (StringId) obj; - if (this.id != null) { - return this.id.equals(other.asString()); - } else if (other.bytes == null) { - return this.asString().equals(other.asString()); - } else { - assert this.bytes != null; - return Bytes.equals(this.bytes, other.asBytes()); - } - } - - @Override - public String toString() { - return this.asString(); - } - } - - public static class LongId extends Number implements Id { - - private static final long serialVersionUID = -7732461469037400190L; - - protected Long id; - - public LongId(long id) { - this.id = id; - } - - public LongId(byte[] bytes) { - this.id = NumericUtil.bytesToLong(bytes); - } - - @Override - public IdType type() { - return IdType.LONG; - } - - @Override - public Object asObject() { - return this.id; - } - - @Override - public String asString() { - // TODO: encode with base64 - return Long.toString(this.id); - } - - @Override - public long asLong() { - return this.id; - } - - @Override - public byte[] asBytes() { - return NumericUtil.longToBytes(this.id); - } - - @Override - public int length() { - return Long.BYTES; - } - - @Override - public int compareTo(Id other) { - int cmp = compareType(this, other); - if (cmp != 0) { - return cmp; - } - return Long.compare(this.id, other.asLong()); - } - - @Override - public int hashCode() { - return Long.hashCode(this.id); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof Number)) { - return false; - } - return this.id == ((Number) other).longValue(); - } - - @Override - public String toString() { - return String.valueOf(this.id); - } - - @Override - public int intValue() { - return this.id.intValue(); - } - - @Override - public long longValue() { - return this.id; - } - - @Override - public float floatValue() { - return this.id; - } - - @Override - public double doubleValue() { - return this.id; - } - } - - public static class UuidId implements Id { - - protected UUID uuid; - - public UuidId(String string) { - this(StringEncoding.uuid(string)); - } - - public UuidId(byte[] bytes) { - this(fromBytes(bytes)); - } - - public UuidId(UUID uuid) { - E.checkArgument(uuid != null, "The uuid can't be null"); - this.uuid = uuid; - } - - @Override - public IdType type() { - return IdType.UUID; - } - - @Override - public Object asObject() { - return this.uuid; - } - - @Override - public String asString() { - return this.uuid.toString(); - } - - @Override - public long asLong() { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] asBytes() { - BytesBuffer buffer = BytesBuffer.allocate(16); - buffer.writeLong(this.uuid.getMostSignificantBits()); - buffer.writeLong(this.uuid.getLeastSignificantBits()); - return buffer.bytes(); - } - - private static UUID fromBytes(byte[] bytes) { - E.checkArgument(bytes != null, "The UUID can't be null"); - BytesBuffer buffer = BytesBuffer.wrap(bytes); - long high = buffer.readLong(); - long low = buffer.readLong(); - return new UUID(high, low); - } - - @Override - public int length() { - return UUID_LENGTH; - } - - @Override - public int compareTo(Id other) { - E.checkNotNull(other, "compare id"); - int cmp = compareType(this, other); - if (cmp != 0) { - return cmp; - } - return this.uuid.compareTo(((UuidId) other).uuid); - } - - @Override - public int hashCode() { - return this.uuid.hashCode(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof UuidId)) { - return false; - } - return this.uuid.equals(((UuidId) other).uuid); - } - - @Override - public String toString() { - return this.uuid.toString(); - } - } - - /** - * This class is just used by backend store for wrapper object as Id - */ - public static class ObjectId implements Id { - - protected Object object; - - public ObjectId(Object object) { - E.checkNotNull(object, "object"); - this.object = object; - } - - @Override - public IdType type() { - return IdType.UNKNOWN; - } - - @Override - public Object asObject() { - return this.object; - } - - @Override - public String asString() { - throw new UnsupportedOperationException(); - } - - @Override - public long asLong() { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] asBytes() { - throw new UnsupportedOperationException(); - } - - @Override - public int length() { - throw new UnsupportedOperationException(); - } - - @Override - public int compareTo(Id o) { - throw new UnsupportedOperationException(); - } - - @Override - public int hashCode() { - return this.object.hashCode(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof ObjectId)) { - return false; - } - return Objects.equals(this.object, ((ObjectId) other).object); - } - - @Override - public String toString() { - return this.object.toString(); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdUtil.java deleted file mode 100644 index 90cd98d4b7..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdUtil.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.id; - -import java.nio.ByteBuffer; - -import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.serializer.BytesBuffer; - -public final class IdUtil { - - public static String writeStoredString(Id id) { - String idString; - switch (id.type()) { - case LONG: - case STRING: - case UUID: - idString = IdGenerator.asStoredString(id); - break; - case EDGE: - idString = EdgeId.asStoredString(id); - break; - default: - throw new AssertionError("Invalid id type " + id.type()); - } - return id.type().prefix() + idString; - } - - public static Id readStoredString(String id) { - IdType type = IdType.valueOfPrefix(id); - String idContent = id.substring(1); - switch (type) { - case LONG: - case STRING: - case UUID: - return IdGenerator.ofStoredString(idContent, type); - case EDGE: - return EdgeId.parseStoredString(idContent); - default: - throw new IllegalArgumentException("Invalid id: " + id); - } - } - - public static Object writeBinString(Id id) { - int len = id.edge() ? BytesBuffer.BUF_EDGE_ID : id.length() + 1; - BytesBuffer buffer = BytesBuffer.allocate(len).writeId(id); - buffer.forReadWritten(); - return buffer.asByteBuffer(); - } - - public static Id readBinString(Object id) { - BytesBuffer buffer = BytesBuffer.wrap((ByteBuffer) id); - return buffer.readId(); - } - - public static String writeString(Id id) { - String idString = id.asString(); - return id.type().prefix() + idString; - } - - public static Id readString(String id) { - IdType type = IdType.valueOfPrefix(id); - String idContent = id.substring(1); - switch (type) { - case LONG: - return IdGenerator.of(Long.parseLong(idContent)); - case STRING: - case UUID: - return IdGenerator.of(idContent, type == IdType.UUID); - case EDGE: - return EdgeId.parse(idContent); - default: - throw new IllegalArgumentException("Invalid id: " + id); - } - } - - public static String writeLong(Id id) { - return String.valueOf(id.asLong()); - } - - public static Id readLong(String id) { - return IdGenerator.of(Long.parseLong(id)); - } - - public static String escape(char splitor, char escape, String... values) { - int length = values.length + 4; - for (String value : values) { - length += value.length(); - } - StringBuilder escaped = new StringBuilder(length); - // Do escape for every item in values - for (String value : values) { - if (escaped.length() > 0) { - escaped.append(splitor); - } - - if (value.indexOf(splitor) == -1) { - escaped.append(value); - continue; - } - - // Do escape for current item - for (int i = 0, n = value.length(); i < n; i++) { - char ch = value.charAt(i); - if (ch == splitor) { - escaped.append(escape); - } - escaped.append(ch); - } - } - return escaped.toString(); - } - - public static String[] unescape(String id, String splitor, String escape) { - /* - * Note that the `splitter`/`escape` maybe special characters in regular - * expressions, but this is a frequently called method, for faster - * execution, we forbid the use of special characters as delimiter - * or escape sign. - * - * The `limit` param -1 in split method can ensure empty string be - * split to a part. - */ - String[] parts = id.split("(?'; - private static final char ID_SPLITOR = ':'; - private static final char NAME_SPLITOR = '!'; - - public static final String ESCAPE_STR = String.valueOf(ESCAPE); - public static final String IDS_SPLITOR_STR = String.valueOf(IDS_SPLITOR); - public static final String ID_SPLITOR_STR = String.valueOf(ID_SPLITOR); - - /****************************** id generate ******************************/ - - /** - * Generate a string id of HugeVertex from Vertex name - */ - @Override - public Id generate(HugeVertex vertex) { - /* - * Hash for row-key which will be evenly distributed. - * We can also use LongEncoding.encode() to encode the int/long hash - * if needed. - * id = String.format("%s%s%s", HashUtil.hash(id), ID_SPLITOR, id); - */ - // TODO: use binary Id with binary fields instead of string id - return splicing(vertex.schemaLabel().id().asString(), vertex.name()); - } - - /** - * Concat multiple ids into one composite id with IDS_SPLITOR - * - * @param ids the string id values to be concatted - * @return concatted string value - */ - public static String concat(String... ids) { - // NOTE: must support string id when using this method - return IdUtil.escape(IDS_SPLITOR, ESCAPE, ids); - } - - /** - * Split a composite id into multiple ids with IDS_SPLITOR - * - * @param ids the string id value to be splitted - * @return splitted string values - */ - public static String[] split(String ids) { - return IdUtil.unescape(ids, IDS_SPLITOR_STR, ESCAPE_STR); - } - - /** - * Concat property values with NAME_SPLITOR - * - * @param values the property values to be concatted - * @return concatted string value - */ - public static String concatValues(List values) { - // Convert the object list to string array - int valuesSize = values.size(); - String[] parts = new String[valuesSize]; - for (int i = 0; i < valuesSize; i++) { - parts[i] = values.get(i).toString(); - } - return IdUtil.escape(NAME_SPLITOR, ESCAPE, parts); - } - - /** - * Concat property values with NAME_SPLITOR - * - * @param values the property values to be concatted - * @return concatted string value - */ - public static String concatValues(Object... values) { - return concatValues(Arrays.asList(values)); - } - - /** - * Concat multiple parts into a single id with ID_SPLITOR - * - * @param parts the string id values to be spliced - * @return spliced id object - */ - public static Id splicing(String... parts) { - String escaped = IdUtil.escape(ID_SPLITOR, ESCAPE, parts); - return IdGenerator.of(escaped); - } - - /** - * Parse a single id into multiple parts with ID_SPLITOR - * - * @param id the id object to be parsed - * @return parsed string id parts - */ - public static String[] parse(Id id) { - return IdUtil.unescape(id.asString(), ID_SPLITOR_STR, ESCAPE_STR); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/IdHolder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/IdHolder.java index ab64959a01..e6fd34ed64 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/IdHolder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/IdHolder.java @@ -23,9 +23,9 @@ import java.util.function.Function; import org.apache.commons.lang.NotImplementedException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.iterator.CIter; import org.apache.hugegraph.iterator.Metadatable; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageEntryIterator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageEntryIterator.java index 17996bae9e..832754afb8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageEntryIterator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageEntryIterator.java @@ -19,7 +19,7 @@ import java.util.Iterator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryBatch; import org.apache.hugegraph.backend.query.QueryBatch.BatchIterator; import org.apache.hugegraph.exception.NotSupportException; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageIds.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageIds.java index 879821f3db..e0e23c5668 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageIds.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageIds.java @@ -19,7 +19,7 @@ import java.util.Set; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import com.google.common.collect.ImmutableSet; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageInfo.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageInfo.java index 3662b6e660..2a913e32ab 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageInfo.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageInfo.java @@ -19,8 +19,8 @@ import java.util.Iterator; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.iterator.Metadatable; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageState.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageState.java index d0cdf74bce..4f08e87dbc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageState.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/PageState.java @@ -17,8 +17,8 @@ package org.apache.hugegraph.backend.page; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.StringEncoding; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/QueryList.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/QueryList.java index d3d8e6960f..7609196982 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/QueryList.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/QueryList.java @@ -22,13 +22,13 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.IdHolder.BatchIdHolder; import org.apache.hugegraph.backend.page.IdHolder.FixedIdHolder; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryBatch; import org.apache.hugegraph.backend.query.QueryBatch.BatchIterator; import org.apache.hugegraph.backend.query.QueryResults; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/SortByCountIdHolderList.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/SortByCountIdHolderList.java index eeac978672..e9b85bd257 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/SortByCountIdHolderList.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/page/SortByCountIdHolderList.java @@ -22,9 +22,9 @@ import java.util.Map; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.IdHolder.FixedIdHolder; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.util.CollectionUtil; import org.apache.hugegraph.util.InsertionOrderUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Aggregate.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Aggregate.java deleted file mode 100644 index e81f0a9d73..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Aggregate.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.query; - -import java.util.Iterator; -import java.util.function.BiFunction; - -import org.apache.tinkerpop.gremlin.util.NumberHelper; - -public class Aggregate { - - private final AggregateFunc func; - private final String column; - - public Aggregate(AggregateFunc func, String column) { - this.func = func; - this.column = column; - } - - public AggregateFunc func() { - return this.func; - } - - public String column() { - return this.column; - } - - public boolean countAll() { - return this.func == AggregateFunc.COUNT && this.column == null; - } - - public Number reduce(Iterator results) { - return this.func.reduce(results); - } - - public Number defaultValue() { - return this.func.defaultValue(); - } - - @Override - public String toString() { - return String.format("%s(%s)", this.func.string(), - this.column == null ? "*" : this.column); - } - - public enum AggregateFunc { - - COUNT("count", 0L, NumberHelper::add), - MAX("max", -Double.MAX_VALUE, NumberHelper::max), - MIN("min", Double.MAX_VALUE, NumberHelper::min), - AVG("avg", 0D, NumberHelper::add), - SUM("sum", 0L, NumberHelper::add); - - private final String name; - private final Number defaultValue; - private final BiFunction merger; - - AggregateFunc(String name, Number defaultValue, - BiFunction merger) { - this.name = name; - this.defaultValue = defaultValue; - this.merger = merger; - } - - public String string() { - return this.name; - } - - public Number defaultValue() { - return this.defaultValue; - } - - public Number reduce(Iterator results) { - Number number; - long count = 0L; - if (results.hasNext()) { - number = results.next(); - count++; - } else { - return this.defaultValue; - } - while (results.hasNext()) { - number = this.merger.apply(number, results.next()); - count++; - } - if (this == AVG) { - number = NumberHelper.div(number, count); - } - return number; - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java deleted file mode 100644 index d956a8ace7..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.query; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.BiFunction; - -import org.apache.commons.lang.ArrayUtils; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.store.Shard; -import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeProperty; -import org.apache.hugegraph.type.define.HugeKeys; -import org.apache.hugegraph.util.Bytes; -import org.apache.hugegraph.util.DateUtil; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.NumericUtil; -import org.apache.tinkerpop.gremlin.process.traversal.PBiPredicate; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public abstract class Condition { - - public enum ConditionType { - NONE, - RELATION, - AND, - OR, - NOT - } - - public enum RelationType implements PBiPredicate { - - EQ("==", RelationType::equals), - - GT(">", (v1, v2) -> { - return compare(v1, v2) > 0; - }), - - GTE(">=", (v1, v2) -> { - return compare(v1, v2) >= 0; - }), - - LT("<", (v1, v2) -> { - return compare(v1, v2) < 0; - }), - - LTE("<=", (v1, v2) -> { - return compare(v1, v2) <= 0; - }), - - NEQ("!=", (v1, v2) -> { - return compare(v1, v2) != 0; - }), - - IN("in", null, Collection.class, (v1, v2) -> { - assert v2 != null; - return ((Collection) v2).contains(v1); - }), - - NOT_IN("notin", null, Collection.class, (v1, v2) -> { - assert v2 != null; - return !((Collection) v2).contains(v1); - }), - - PREFIX("prefix", Id.class, Id.class, (v1, v2) -> { - assert v2 != null; - return v1 != null && Bytes.prefixWith(((Id) v2).asBytes(), - ((Id) v1).asBytes()); - }), - - TEXT_CONTAINS("textcontains", String.class, String.class, (v1, v2) -> { - // TODO: support collection-property textcontains - return v1 != null && ((String) v1).contains((String) v2); - }), - - TEXT_CONTAINS_ANY("textcontainsany", String.class, Collection.class, (v1, v2) -> { - assert v2 != null; - if (v1 == null) { - return false; - } - - @SuppressWarnings("unchecked") - Collection words = (Collection) v2; - - for (String word : words) { - if (((String) v1).contains(word)) { - return true; - } - } - return false; - }), - - CONTAINS("contains", Collection.class, null, (v1, v2) -> { - assert v2 != null; - return v1 != null && ((Collection) v1).contains(v2); - }), - - CONTAINS_VALUE("containsv", Map.class, null, (v1, v2) -> { - assert v2 != null; - return v1 != null && ((Map) v1).containsValue(v2); - }), - - CONTAINS_KEY("containsk", Map.class, null, (v1, v2) -> { - assert v2 != null; - return v1 != null && ((Map) v1).containsKey(v2); - }), - - SCAN("scan", (v1, v2) -> { - assert v2 != null; - /* - * TODO: we still have no way to determine accurately for all - * backend scan implementations. - */ - return true; - }); - - private static final Set RANGE_TYPES = - ImmutableSet.of(GT, GTE, LT, LTE); - - private static final Set UNFLATTEN_TYPES = - ImmutableSet.of(IN, NOT_IN, TEXT_CONTAINS_ANY); - - private final String operator; - private final BiFunction tester; - private final Class v1Class; - private final Class v2Class; - - RelationType(String op, - BiFunction tester) { - this(op, null, null, tester); - } - - RelationType(String op, Class v1Class, Class v2Class, - BiFunction tester) { - this.operator = op; - this.tester = tester; - this.v1Class = v1Class; - this.v2Class = v2Class; - } - - public String string() { - return this.operator; - } - - @Override - public String getPredicateName() { - return this.operator; - } - - /** - * Determine two values of any type equal - * - * @param first is actual value - * @param second is value in query condition - * @return true if equal, otherwise false - */ - private static boolean equals(final Object first, - final Object second) { - assert second != null; - if (first instanceof Id) { - if (second instanceof String) { - return second.equals(((Id) first).asString()); - } else if (second instanceof Long) { - return second.equals(((Id) first).asLong()); - } - } else if (second instanceof Number) { - return compare(first, second) == 0; - } else if (second.getClass().isArray()) { - return ArrayUtils.isEquals(first, second); - } - - return Objects.equals(first, second); - } - - /** - * Determine two numbers equal - * - * @param first is actual value, might be Number/Date or String, It is - * probably that the `first` is serialized to String. - * @param second is value in query condition, must be Number/Date/Boolean - * @return the value 0 if first is numerically equal to second; - * a value less than 0 if first is numerically less than - * second; and a value greater than 0 if first is - * numerically greater than second. - */ - private static int compare(final Object first, final Object second) { - assert second != null; - if (second instanceof Number) { - return NumericUtil.compareNumber(first == null ? 0 : first, - (Number) second); - } else if (second instanceof Date) { - return compareDate(first, (Date) second); - } else if (second instanceof Boolean) { - return compareBoolean(first, (Boolean) second); - } - - throw new IllegalArgumentException(String.format( - "Can't compare between %s(%s) and %s(%s)", first, - first == null ? null : first.getClass().getSimpleName(), - second, second.getClass().getSimpleName())); - } - - private static int compareDate(Object first, Date second) { - if (first == null) { - first = DateUtil.DATE_ZERO; - } - if (first instanceof Date) { - return ((Date) first).compareTo(second); - } - - throw new IllegalArgumentException(String.format( - "Can't compare between %s(%s) and %s(%s)", - first, first.getClass().getSimpleName(), - second, second.getClass().getSimpleName())); - } - - private static int compareBoolean(Object first, Boolean second) { - if (first instanceof Boolean) { - return Boolean.compare((Boolean) first, second); - } - - throw new IllegalArgumentException(String.format( - "Can't compare between %s(%s) and %s(%s)", - first, first == null ? null : - first.getClass().getSimpleName(), - second, second.getClass().getSimpleName())); - } - - private void checkBaseType(Object value, Class clazz) { - if (!clazz.isInstance(value)) { - String valueClass = value == null ? "null" : - value.getClass().getSimpleName(); - E.checkArgument(false, - "Can't execute `%s` on type %s, expect %s", - this.operator, valueClass, - clazz.getSimpleName()); - } - } - - private void checkValueType(Object value, Class clazz) { - if (!clazz.isInstance(value)) { - String valueClass = value == null ? "null" : - value.getClass().getSimpleName(); - E.checkArgument(false, - "Can't test '%s'(%s) for `%s`, expect %s", - value, valueClass, this.operator, - clazz.getSimpleName()); - } - } - - @Override - public boolean test(Object first, Object second) { - E.checkState(this.tester != null, "Can't test %s", this.name()); - E.checkArgument(second != null, - "Can't test null value for `%s`", this.operator); - if (this.v1Class != null) { - this.checkBaseType(first, this.v1Class); - } - if (this.v2Class != null) { - this.checkValueType(second, this.v2Class); - } - return this.tester.apply(first, second); - } - - public boolean isRangeType() { - return RANGE_TYPES.contains(this); - } - - public boolean isSearchType() { - return this == TEXT_CONTAINS || this == TEXT_CONTAINS_ANY; - } - - public boolean isSecondaryType() { - return this == EQ; - } - } - - public abstract ConditionType type(); - - public abstract boolean isSysprop(); - - public abstract List relations(); - - public abstract boolean test(Object value); - - public abstract boolean test(HugeElement element); - - public abstract Condition copy(); - - public abstract Condition replace(Relation from, Relation to); - - public Condition and(Condition other) { - return new And(this, other); - } - - public Condition or(Condition other) { - return new Or(this, other); - } - - public boolean isRelation() { - return this.type() == ConditionType.RELATION; - } - - public boolean isLogic() { - return this.type() == ConditionType.AND || - this.type() == ConditionType.OR || - this.type() == ConditionType.NOT; - } - - public boolean isFlattened() { - return this.isRelation(); - } - - public static Condition and(Condition left, Condition right) { - return new And(left, right); - } - - public static Condition or(Condition left, Condition right) { - return new Or(left, right); - } - - public static Condition not(Condition condition) { - return new Not(condition); - } - - public static Relation eq(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.EQ, value); - } - - public static Relation gt(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.GT, value); - } - - public static Relation gte(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.GTE, value); - } - - public static Relation lt(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.LT, value); - } - - public static Relation lte(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.LTE, value); - } - - public static Relation neq(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.NEQ, value); - } - - public static Condition in(HugeKeys key, List value) { - return new SyspropRelation(key, RelationType.IN, value); - } - - public static Condition nin(HugeKeys key, List value) { - return new SyspropRelation(key, RelationType.NOT_IN, value); - } - - public static Condition prefix(HugeKeys key, Id value) { - return new SyspropRelation(key, RelationType.PREFIX, value); - } - - public static Condition containsValue(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.CONTAINS_VALUE, value); - } - - public static Condition containsKey(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.CONTAINS_KEY, value); - } - - public static Condition contains(HugeKeys key, Object value) { - return new SyspropRelation(key, RelationType.CONTAINS, value); - } - - public static Condition scan(String start, String end) { - Shard value = new Shard(start, end, 0); - return new SyspropRelation(HugeKeys.ID, RelationType.SCAN, value); - } - - public static Relation eq(Id key, Object value) { - return new UserpropRelation(key, RelationType.EQ, value); - } - - public static Relation gt(Id key, Object value) { - return new UserpropRelation(key, RelationType.GT, value); - } - - public static Relation gte(Id key, Object value) { - return new UserpropRelation(key, RelationType.GTE, value); - } - - public static Relation lt(Id key, Object value) { - return new UserpropRelation(key, RelationType.LT, value); - } - - public static Relation lte(Id key, Object value) { - return new UserpropRelation(key, RelationType.LTE, value); - } - - public static Relation neq(Id key, Object value) { - return new UserpropRelation(key, RelationType.NEQ, value); - } - - public static Relation in(Id key, List value) { - return new UserpropRelation(key, RelationType.IN, value); - } - - public static Relation nin(Id key, List value) { - return new UserpropRelation(key, RelationType.NOT_IN, value); - } - - public static Relation textContains(Id key, String word) { - return new UserpropRelation(key, RelationType.TEXT_CONTAINS, word); - } - - public static Relation textContainsAny(Id key, Set words) { - return new UserpropRelation(key, RelationType.TEXT_CONTAINS_ANY, words); - } - - public static Condition contains(Id key, Object value) { - return new UserpropRelation(key, RelationType.CONTAINS, value); - } - - /** - * Condition defines - */ - public abstract static class BinCondition extends Condition { - - private Condition left; - private Condition right; - - public BinCondition(Condition left, Condition right) { - E.checkNotNull(left, "left condition"); - E.checkNotNull(right, "right condition"); - this.left = left; - this.right = right; - } - - public Condition left() { - return this.left; - } - - public Condition right() { - return this.right; - } - - @Override - public boolean isSysprop() { - return this.left.isSysprop() && this.right.isSysprop(); - } - - @Override - public List relations() { - List list = new ArrayList<>(this.left.relations()); - list.addAll(this.right.relations()); - return list; - } - - @Override - public Condition replace(Relation from, Relation to) { - this.left = this.left.replace(from, to); - this.right = this.right.replace(from, to); - return this; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append(this.left).append(' '); - sb.append(this.type().name()).append(' '); - sb.append(this.right); - return sb.toString(); - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof BinCondition)) { - return false; - } - BinCondition other = (BinCondition) object; - return this.type().equals(other.type()) && - this.left().equals(other.left()) && - this.right().equals(other.right()); - } - - @Override - public int hashCode() { - return this.type().hashCode() ^ - this.left().hashCode() ^ - this.right().hashCode(); - } - } - - public static class And extends BinCondition { - - public And(Condition left, Condition right) { - super(left, right); - } - - @Override - public ConditionType type() { - return ConditionType.AND; - } - - @Override - public boolean test(Object value) { - return this.left().test(value) && this.right().test(value); - } - - @Override - public boolean test(HugeElement element) { - return this.left().test(element) && this.right().test(element); - } - - @Override - public Condition copy() { - return new And(this.left().copy(), this.right().copy()); - } - } - - public static class Or extends BinCondition { - - public Or(Condition left, Condition right) { - super(left, right); - } - - @Override - public ConditionType type() { - return ConditionType.OR; - } - - @Override - public boolean test(Object value) { - return this.left().test(value) || this.right().test(value); - } - - @Override - public boolean test(HugeElement element) { - return this.left().test(element) || this.right().test(element); - } - - @Override - public Condition copy() { - return new Or(this.left().copy(), this.right().copy()); - } - } - - public static class Not extends Condition { - - Condition condition; - - public Not(Condition condition) { - super(); - this.condition = condition; - } - - public Condition condition() { - return condition; - } - - @Override - public ConditionType type() { - return ConditionType.NOT; - } - - @Override - public boolean test(Object value) { - return !this.condition.test(value); - } - - @Override - public boolean test(HugeElement element) { - return !this.condition.test(element); - } - - @Override - public Condition copy() { - return new Not(this.condition.copy()); - } - - @Override - public boolean isSysprop() { - return this.condition.isSysprop(); - } - - @Override - public List relations() { - return new ArrayList(this.condition.relations()); - } - - @Override - public Condition replace(Relation from, Relation to) { - this.condition = this.condition.replace(from, to); - return this; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append(this.type().name()).append(' '); - sb.append(this.condition); - return sb.toString(); - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof Not)) { - return false; - } - Not other = (Not) object; - return this.type().equals(other.type()) && - this.condition.equals(other.condition()); - } - - @Override - public int hashCode() { - return this.type().hashCode() ^ - this.condition.hashCode(); - } - } - - public abstract static class Relation extends Condition { - - // Relational operator (like: =, >, <, in, ...) - protected RelationType relation; - // Single-type value or a list of single-type value - protected Object value; - - // The key serialized(code/string) by backend store. - protected Object serialKey; - // The value serialized(code/string) by backend store. - protected Object serialValue; - - @Override - public ConditionType type() { - return ConditionType.RELATION; - } - - public RelationType relation() { - return this.relation; - } - - public Object value() { - return this.value; - } - - public void value(Object value) { - this.value = value; - } - - public void serialKey(Object key) { - this.serialKey = key; - } - - public Object serialKey() { - return this.serialKey != null ? this.serialKey : this.key(); - } - - public void serialValue(Object value) { - this.serialValue = value; - } - - public Object serialValue() { - return this.serialValue != null ? this.serialValue : this.value(); - } - - @Override - public boolean test(Object value) { - return this.relation.test(value, this.value()); - } - - @Override - public boolean isFlattened() { - return !RelationType.UNFLATTEN_TYPES.contains(this.relation); - } - - @Override - public List relations() { - return ImmutableList.of(this); - } - - @Override - public Condition replace(Relation from, Relation to) { - if (this == from) { - return to; - } else { - return this; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append(this.key()).append(' '); - sb.append(this.relation.string()).append(' '); - sb.append(this.value); - return sb.toString(); - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof Relation)) { - return false; - } - Relation other = (Relation) object; - return this.relation().equals(other.relation()) && - this.key().equals(other.key()) && - this.value().equals(other.value()); - } - - @Override - public int hashCode() { - return this.type().hashCode() ^ - this.relation().hashCode() ^ - this.key().hashCode() ^ - this.value().hashCode(); - } - - @Override - public abstract boolean isSysprop(); - - public abstract Object key(); - - @Override - public abstract Relation copy(); - } - - public static class SyspropRelation extends Relation { - - private final HugeKeys key; - - public SyspropRelation(HugeKeys key, Object value) { - this(key, RelationType.EQ, value); - } - - public SyspropRelation(HugeKeys key, RelationType op, Object value) { - E.checkNotNull(op, "relation type"); - this.key = key; - this.relation = op; - this.value = value; - } - - @Override - public HugeKeys key() { - return this.key; - } - - @Override - public boolean isSysprop() { - return true; - } - - @Override - public boolean test(HugeElement element) { - E.checkNotNull(element, "element"); - Object value = element.sysprop(this.key); - return this.relation.test(value, this.value()); - } - - @Override - public Relation copy() { - Relation clone = new SyspropRelation(this.key, this.relation(), - this.value); - clone.serialKey(this.serialKey); - clone.serialValue(this.serialValue); - return clone; - } - } - - public static class FlattenSyspropRelation extends SyspropRelation { - - public FlattenSyspropRelation(SyspropRelation relation) { - super(relation.key(), relation.relation(), relation.value()); - } - - @Override - public boolean isFlattened() { - return true; - } - } - - public static class UserpropRelation extends Relation { - - // Id of property key - private final Id key; - - public UserpropRelation(Id key, Object value) { - this(key, RelationType.EQ, value); - } - - public UserpropRelation(Id key, RelationType op, Object value) { - E.checkNotNull(op, "relation type"); - this.key = key; - this.relation = op; - this.value = value; - } - - @Override - public Id key() { - return this.key; - } - - @Override - public boolean isSysprop() { - return false; - } - - @Override - public boolean test(HugeElement element) { - HugeProperty prop = element.getProperty(this.key); - Object value = prop != null ? prop.value() : null; - if (value == null) { - /* - * Fix #611 - * TODO: It's possible some scenes can't be returned false - * directly, such as: EQ with p1 == null, it should be returned - * true, but the query has(p, null) is not allowed by - * TraversalUtil.validPredicateValue(). - */ - return false; - } - return this.relation.test(value, this.value()); - } - - @Override - public Relation copy() { - Relation clone = new UserpropRelation(this.key, this.relation(), - this.value); - clone.serialKey(this.serialKey); - clone.serialValue(this.serialValue); - return clone; - } - } - - public static class RangeConditions { - - private Object keyEq = null; - private Object keyMin = null; - private boolean keyMinEq = false; - private Object keyMax = null; - private boolean keyMaxEq = false; - - public RangeConditions(List conditions) { - for (Condition c : conditions) { - Relation r = (Relation) c; - switch (r.relation()) { - case EQ: - this.keyEq = r.value(); - break; - case GTE: - this.keyMinEq = true; - this.keyMin = r.value(); - break; - case GT: - this.keyMin = r.value(); - break; - case LTE: - this.keyMaxEq = true; - this.keyMax = r.value(); - break; - case LT: - this.keyMax = r.value(); - break; - default: - E.checkArgument(false, "Unsupported relation '%s'", - r.relation()); - } - } - } - - public Object keyEq() { - return this.keyEq; - } - - public Object keyMin() { - return this.keyMin; - } - - public Object keyMax() { - return this.keyMax; - } - - public boolean keyMinEq() { - return this.keyMinEq; - } - - public boolean keyMaxEq() { - return this.keyMaxEq; - } - - public boolean hasRange() { - return this.keyMin != null || this.keyMax != null; - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java deleted file mode 100644 index 6da8da23db..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.query; - -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.Condition.RelationType; -import org.apache.hugegraph.backend.query.serializer.QueryAdapter; -import org.apache.hugegraph.backend.query.serializer.QueryIdAdapter; -import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeProperty; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.HugeKeys; -import org.apache.hugegraph.util.CollectionUtil; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.InsertionOrderUtil; -import org.apache.hugegraph.util.LongEncoding; -import org.apache.hugegraph.util.NumericUtil; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -public class ConditionQuery extends IdQuery { - - public static final char INDEX_SYM_MIN = '\u0000'; - public static final String INDEX_SYM_ENDING = "\u0000"; - public static final String INDEX_SYM_NULL = "\u0001"; - public static final String INDEX_SYM_EMPTY = "\u0002"; - public static final char INDEX_SYM_MAX = '\u0003'; - - // Note: here we use "new String" to distinguish normal string code - public static final String INDEX_VALUE_NULL = ""; - public static final String INDEX_VALUE_EMPTY = ""; - - public static final Set IGNORE_SYM_SET; - - static { - List list = new ArrayList<>(INDEX_SYM_MAX - INDEX_SYM_MIN); - for (char ch = INDEX_SYM_MIN; ch <= INDEX_SYM_MAX; ch++) { - list.add(String.valueOf(ch)); - } - IGNORE_SYM_SET = ImmutableSet.copyOf(list); - } - - private static final List EMPTY_CONDITIONS = ImmutableList.of(); - - private static final Gson gson = new GsonBuilder() - .registerTypeAdapter(Condition.class, new QueryAdapter()) - .registerTypeAdapter(Id.class, new QueryIdAdapter()) - .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") - .create(); - - // Conditions will be contacted with `and` by default - private List conditions = EMPTY_CONDITIONS; - - private OptimizedType optimizedType = OptimizedType.NONE; - private ResultsFilter resultsFilter = null; - private Element2IndexValueMap element2IndexValueMap = null; - - public ConditionQuery(HugeType resultType) { - super(resultType); - } - - public ConditionQuery(HugeType resultType, Query originQuery) { - super(resultType, originQuery); - } - - public ConditionQuery query(Condition condition) { - // Query by id (HugeGraph-259) - if (condition instanceof Relation) { - Relation relation = (Relation) condition; - if (relation.key().equals(HugeKeys.ID) && - relation.relation() == RelationType.EQ) { - E.checkArgument(relation.value() instanceof Id, - "Invalid id value '%s'", relation.value()); - super.query((Id) relation.value()); - return this; - } - } - - if (this.conditions == EMPTY_CONDITIONS) { - this.conditions = InsertionOrderUtil.newList(); - } - this.conditions.add(condition); - return this; - } - - public ConditionQuery query(List conditions) { - for (Condition condition : conditions) { - this.query(condition); - } - return this; - } - - public ConditionQuery eq(HugeKeys key, Object value) { - // Filter value by key - return this.query(Condition.eq(key, value)); - } - - public ConditionQuery gt(HugeKeys key, Object value) { - return this.query(Condition.gt(key, value)); - } - - public ConditionQuery gte(HugeKeys key, Object value) { - return this.query(Condition.gte(key, value)); - } - - public ConditionQuery lt(HugeKeys key, Object value) { - return this.query(Condition.lt(key, value)); - } - - public ConditionQuery lte(HugeKeys key, Object value) { - return this.query(Condition.lte(key, value)); - } - - public ConditionQuery neq(HugeKeys key, Object value) { - return this.query(Condition.neq(key, value)); - } - - public ConditionQuery prefix(HugeKeys key, Id value) { - return this.query(Condition.prefix(key, value)); - } - - public ConditionQuery key(HugeKeys key, Object value) { - return this.query(Condition.containsKey(key, value)); - } - - public ConditionQuery scan(String start, String end) { - return this.query(Condition.scan(start, end)); - } - - @Override - public int conditionsSize() { - return this.conditions.size(); - } - - @Override - public Collection conditions() { - return Collections.unmodifiableList(this.conditions); - } - - public void resetConditions(List conditions) { - this.conditions = conditions; - } - - public void resetConditions() { - this.conditions = EMPTY_CONDITIONS; - } - - public void recordIndexValue(Id propertyId, Id id, Object indexValue) { - this.element2IndexValueMap().addIndexValue(propertyId, id, indexValue); - } - - public void selectedIndexField(Id indexField) { - this.element2IndexValueMap().selectedIndexField(indexField); - } - - public void removeElementLeftIndex(Id elementId) { - if (this.element2IndexValueMap == null) { - return; - } - this.element2IndexValueMap.removeElementLeftIndex(elementId); - } - - public boolean existLeftIndex(Id elementId) { - return this.getLeftIndexOfElement(elementId) != null; - } - - public Set getLeftIndexOfElement(Id elementId) { - if (this.element2IndexValueMap == null) { - return null; - } - return this.element2IndexValueMap.getLeftIndex(elementId); - } - - private Element2IndexValueMap element2IndexValueMap() { - if (this.element2IndexValueMap == null) { - this.element2IndexValueMap = new Element2IndexValueMap(); - } - return this.element2IndexValueMap; - } - - public List relations() { - List relations = new ArrayList<>(); - for (Condition c : this.conditions) { - relations.addAll(c.relations()); - } - return relations; - } - - public Relation relation(Id key) { - for (Relation r : this.relations()) { - if (r.key().equals(key)) { - return r; - } - } - return null; - } - - public boolean containsLabelOrUserpropRelation() { - for (Condition c : this.conditions) { - while (c instanceof Condition.Not) { - c = ((Condition.Not) c).condition(); - } - if (c.isLogic()) { - Condition.BinCondition binCondition = - (Condition.BinCondition) c; - ConditionQuery query = new ConditionQuery(HugeType.EDGE); - query.query(binCondition.left()); - query.query(binCondition.right()); - if (query.containsLabelOrUserpropRelation()) { - return true; - } - } else { - Condition.Relation r = (Condition.Relation) c; - if (r.key().equals(HugeKeys.LABEL) || - c instanceof Condition.UserpropRelation) { - return true; - } - } - } - return false; - } - - @Watched - public T condition(Object key) { - List valuesEQ = InsertionOrderUtil.newList(); - List valuesIN = InsertionOrderUtil.newList(); - for (Condition c : this.conditions) { - if (c.isRelation()) { - Condition.Relation r = (Condition.Relation) c; - if (r.key().equals(key)) { - if (r.relation() == RelationType.EQ) { - valuesEQ.add(r.value()); - } else if (r.relation() == RelationType.IN) { - Object value = r.value(); - assert value instanceof List; - valuesIN.add(value); - } - } - } - } - if (valuesEQ.isEmpty() && valuesIN.isEmpty()) { - return null; - } - if (valuesEQ.size() == 1 && valuesIN.isEmpty()) { - @SuppressWarnings("unchecked") - T value = (T) valuesEQ.get(0); - return value; - } - if (valuesEQ.isEmpty() && valuesIN.size() == 1) { - @SuppressWarnings("unchecked") - T value = (T) valuesIN.get(0); - return value; - } - - boolean initialized = false; - Set intersectValues = InsertionOrderUtil.newSet(); - for (Object value : valuesEQ) { - List valueAsList = ImmutableList.of(value); - if (!initialized) { - intersectValues.addAll(valueAsList); - initialized = true; - } else { - CollectionUtil.intersectWithModify(intersectValues, - valueAsList); - } - } - for (Object value : valuesIN) { - @SuppressWarnings("unchecked") - List valueAsList = (List) value; - if (!initialized) { - intersectValues.addAll(valueAsList); - initialized = true; - } else { - CollectionUtil.intersectWithModify(intersectValues, - valueAsList); - } - } - - if (intersectValues.isEmpty()) { - return null; - } - E.checkState(intersectValues.size() == 1, - "Illegal key '%s' with more than one value: %s", - key, intersectValues); - @SuppressWarnings("unchecked") - T value = (T) intersectValues.iterator().next(); - return value; - } - - public void unsetCondition(Object key) { - this.conditions.removeIf(c -> c.isRelation() && ((Relation) c).key().equals(key)); - } - - public boolean containsCondition(HugeKeys key) { - for (Condition c : this.conditions) { - if (c.isRelation()) { - Condition.Relation r = (Condition.Relation) c; - if (r.key().equals(key)) { - return true; - } - } - } - return false; - } - - public boolean containsCondition(Condition.RelationType type) { - for (Relation r : this.relations()) { - if (r.relation().equals(type)) { - return true; - } - } - return false; - } - - public boolean containsScanCondition() { - return this.containsCondition(Condition.RelationType.SCAN); - } - - public boolean containsRelation(HugeKeys key, Condition.RelationType type) { - for (Relation r : this.relations()) { - if (r.key().equals(key) && r.relation().equals(type)) { - return true; - } - } - return false; - } - - public boolean containsRelation(Condition.RelationType type) { - for (Relation r : this.relations()) { - if (r.relation().equals(type)) { - return true; - } - } - return false; - } - - public boolean containsScanRelation() { - return this.containsRelation(Condition.RelationType.SCAN); - } - - public boolean containsContainsCondition(Id key) { - for (Relation r : this.relations()) { - if (r.key().equals(key)) { - return r.relation().equals(RelationType.CONTAINS) || - r.relation().equals(RelationType.TEXT_CONTAINS); - } - } - return false; - } - - public boolean allSysprop() { - for (Condition c : this.conditions) { - if (!c.isSysprop()) { - return false; - } - } - return true; - } - - public boolean allRelation() { - for (Condition c : this.conditions) { - if (!c.isRelation()) { - return false; - } - } - return true; - } - - public List syspropConditions() { - this.checkFlattened(); - List conds = new ArrayList<>(); - for (Condition c : this.conditions) { - if (c.isSysprop()) { - conds.add(c); - } - } - return conds; - } - - public List syspropConditions(HugeKeys key) { - this.checkFlattened(); - List conditions = new ArrayList<>(); - for (Condition condition : this.conditions) { - Relation relation = (Relation) condition; - if (relation.key().equals(key)) { - conditions.add(relation); - } - } - return conditions; - } - - public List userpropConditions() { - this.checkFlattened(); - List conds = new ArrayList<>(); - for (Condition c : this.conditions) { - if (!c.isSysprop()) { - conds.add(c); - } - } - return conds; - } - - public List userpropConditions(Id key) { - this.checkFlattened(); - List conditions = new ArrayList<>(); - for (Condition condition : this.conditions) { - Relation relation = (Relation) condition; - if (relation.key().equals(key)) { - conditions.add(relation); - } - } - return conditions; - } - - public List userpropRelations() { - List relations = new ArrayList<>(); - for (Relation r : this.relations()) { - if (!r.isSysprop()) { - relations.add(r); - } - } - return relations; - } - - public void resetUserpropConditions() { - this.conditions.removeIf(condition -> !condition.isSysprop()); - } - - public Set userpropKeys() { - Set keys = new LinkedHashSet<>(); - for (Relation r : this.relations()) { - if (!r.isSysprop()) { - Condition.UserpropRelation ur = (Condition.UserpropRelation) r; - keys.add(ur.key()); - } - } - return keys; - } - - /** - * This method is only used for secondary index scenario, - * its relation must be EQ - * - * @param fields the user property fields - * @return the corresponding user property serial values of fields - */ - public String userpropValuesString(List fields) { - List values = new ArrayList<>(fields.size()); - for (Id field : fields) { - boolean got = false; - for (Relation r : this.userpropRelations()) { - if (r.key().equals(field) && !r.isSysprop()) { - E.checkState(r.relation == RelationType.EQ || - r.relation == RelationType.CONTAINS, - "Method userpropValues(List) only " + - "used for secondary index, " + - "relation must be EQ or CONTAINS, but got %s", - r.relation()); - values.add(r.serialValue()); - got = true; - } - } - if (!got) { - throw new BackendException( - "No such userprop named '%s' in the query '%s'", - field, this); - } - } - return concatValues(values); - } - - public Set userpropValues(Id field) { - Set values = new HashSet<>(); - for (Relation r : this.userpropRelations()) { - if (r.key().equals(field)) { - values.add(r.serialValue()); - } - } - return values; - } - - public Object userpropValue(Id field) { - Set values = this.userpropValues(field); - if (values.isEmpty()) { - return null; - } - E.checkState(values.size() == 1, - "Expect one user-property value of field '%s', " + - "but got '%s'", field, values.size()); - return values.iterator().next(); - } - - public boolean hasRangeCondition() { - // NOTE: we need to judge all the conditions, including the nested - for (Condition.Relation r : this.relations()) { - if (r.relation().isRangeType()) { - return true; - } - } - return false; - } - - public boolean hasSearchCondition() { - // NOTE: we need to judge all the conditions, including the nested - for (Condition.Relation r : this.relations()) { - if (r.relation().isSearchType()) { - return true; - } - } - return false; - } - - public boolean hasSecondaryCondition() { - // NOTE: we need to judge all the conditions, including the nested - for (Condition.Relation r : this.relations()) { - if (r.relation().isSecondaryType()) { - return true; - } - } - return false; - } - - public boolean hasNeqCondition() { - // NOTE: we need to judge all the conditions, including the nested - for (Condition.Relation r : this.relations()) { - if (r.relation() == RelationType.NEQ) { - return true; - } - } - return false; - } - - public boolean matchUserpropKeys(List keys) { - Set conditionKeys = this.userpropKeys(); - return !keys.isEmpty() && conditionKeys.containsAll(keys); - } - - @Override - public ConditionQuery copy() { - ConditionQuery query = (ConditionQuery) super.copy(); - query.originQuery(this); - if (query.conditions != EMPTY_CONDITIONS) { - query.conditions = InsertionOrderUtil.newList(this.conditions); - } - query.optimizedType = OptimizedType.NONE; - query.resultsFilter = null; - - return query; - } - - public ConditionQuery copyAndResetUnshared() { - ConditionQuery query = this.copy(); - // These fields should not be shared by multiple sub-query - query.optimizedType = OptimizedType.NONE; - query.resultsFilter = null; - return query; - } - - public Condition.Relation copyRelationAndUpdateQuery(Object key) { - Condition.Relation copyRes = null; - for (int i = 0; i < this.conditions.size(); i++) { - Condition c = this.conditions.get(i); - if (c.isRelation()) { - Condition.Relation r = (Condition.Relation) c; - if (r.key().equals(key)) { - copyRes = r.copy(); - this.conditions.set(i, copyRes); - break; - } - } - } - E.checkArgument(copyRes != null, "Failed to copy Condition.Relation: %s", key); - return copyRes; - } - - @Override - public boolean test(HugeElement element) { - return this.test(element, this.resultsFilter); - } - - public boolean test(HugeElement element, ResultsFilter filter) { - if (!this.ids().isEmpty() && !super.test(element)) { - return false; - } - - /* - * Currently results-filter is used to filter unmatched results returned - * by search index, and there may be multiple results-filter for every - * sub-query like within() + Text.contains(). - * We can't use sub-query results-filter here for fresh element which is - * not committed to backend store, because it's not from a sub-query. - */ - if (filter != null && !element.fresh()) { - return filter.test(element); - } - - /* - * NOTE: seems need to keep call checkRangeIndex() for each condition, - * so don't break early even if test() return false. - */ - boolean valid = true; - Map rangeIndexMatches = null; - if (this.element2IndexValueMap != null) { - rangeIndexMatches = new HashMap<>(); - } - for (Condition cond : this.conditions) { - valid &= cond.test(element); - if (this.element2IndexValueMap != null) { - valid &= this.element2IndexValueMap.checkRangeIndex( - element, cond, rangeIndexMatches); - } - } - return valid; - } - - public void checkFlattened() { - E.checkState(this.isFlattened(), - "Query has none-flatten condition: %s", this); - } - - public boolean isFlattened() { - for (Condition condition : this.conditions) { - if (!condition.isFlattened()) { - return false; - } - } - return true; - } - - public boolean mayHasDupKeys(Set keys) { - Map keyCounts = new HashMap<>(); - for (Condition condition : this.conditions) { - if (!condition.isRelation()) { - // Assume may exist duplicate keys when has nested conditions - return true; - } - Relation relation = (Relation) condition; - if (keys.contains(relation.key())) { - int keyCount = keyCounts.getOrDefault(relation.key(), 0); - if (++keyCount > 1) { - return true; - } - keyCounts.put((HugeKeys) relation.key(), keyCount); - } - } - return false; - } - - public void optimized(OptimizedType optimizedType) { - assert this.optimizedType.ordinal() <= optimizedType.ordinal() : - this.optimizedType + " !<= " + optimizedType; - this.optimizedType = optimizedType; - - Query originQuery = this.originQuery(); - if (originQuery instanceof ConditionQuery) { - ConditionQuery cq = ((ConditionQuery) originQuery); - /* - * Two sub-query(flatten) will both set optimized of originQuery, - * here we just keep the higher one, this may not be a perfect way - */ - if (optimizedType.ordinal() > cq.optimized().ordinal()) { - cq.optimized(optimizedType); - } - } - } - - public OptimizedType optimized() { - return this.optimizedType; - } - - public void registerResultsFilter(ResultsFilter filter) { - assert this.resultsFilter == null; - this.resultsFilter = filter; - } - - ResultsFilter resultsFilter() { - return this.resultsFilter; - } - - public ConditionQuery originConditionQuery() { - Query originQuery = this.originQuery(); - if (!(originQuery instanceof ConditionQuery)) { - return null; - } - - while (originQuery.originQuery() instanceof ConditionQuery) { - originQuery = originQuery.originQuery(); - } - return (ConditionQuery) originQuery; - } - - public static String concatValues(List values) { - assert !values.isEmpty(); - List newValues = new ArrayList<>(values.size()); - for (Object v : values) { - newValues.add(concatValues(v)); - } - return SplicingIdGenerator.concatValues(newValues); - } - - public static String concatValues(Object value) { - if (value instanceof String) { - return escapeSpecialValueIfNeeded((String) value); - } - if (value instanceof List) { - return concatValues((List) value); - } else if (needConvertNumber(value)) { - return LongEncoding.encodeNumber(value); - } else { - return escapeSpecialValueIfNeeded(value.toString()); - } - } - - public static ConditionQuery fromBytes(byte[] bytes) { - Gson gson = new GsonBuilder() - .registerTypeAdapter(Condition.class, new QueryAdapter()) - .registerTypeAdapter(Id.class, new QueryIdAdapter()) - .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") - .create(); - String cqs = new String(bytes, StandardCharsets.UTF_8); - ConditionQuery conditionQuery = gson.fromJson(cqs, ConditionQuery.class); - - return conditionQuery; - } - - private static boolean needConvertNumber(Object value) { - // Numeric or date values should be converted to number from string - return NumericUtil.isNumber(value) || value instanceof Date; - } - - private static String escapeSpecialValueIfNeeded(String value) { - if (value.isEmpty()) { - // Escape empty String to INDEX_SYM_EMPTY (char `\u0002`) - value = INDEX_SYM_EMPTY; - } else if (value == INDEX_VALUE_EMPTY) { - value = ""; - } else if (value == INDEX_VALUE_NULL) { - value = INDEX_SYM_NULL; - } else { - char ch = value.charAt(0); - if (ch <= INDEX_SYM_MAX) { - /* - * Special symbols can't be used due to impossible to parse, - * and treat it as illegal value for the origin text property. - * TODO: escape special symbols - */ - E.checkArgument(false, - "Illegal leading char '\\u%s' " + - "in index property: '%s'", - (int) ch, value); - } - } - return value; - } - - public enum OptimizedType { - NONE, - PRIMARY_KEY, - SORT_KEYS, - INDEX, - INDEX_FILTER - } - - public static final class Element2IndexValueMap { - - private final Map> leftIndexMap; - private final Map>> filed2IndexValues; - private Id selectedIndexField; - - public Element2IndexValueMap() { - this.filed2IndexValues = new HashMap<>(); - this.leftIndexMap = new HashMap<>(); - } - - public void addIndexValue(Id indexField, Id elementId, - Object indexValue) { - if (!this.filed2IndexValues.containsKey(indexField)) { - this.filed2IndexValues.putIfAbsent(indexField, new HashMap<>()); - } - Map> element2IndexValueMap = - this.filed2IndexValues.get(indexField); - if (element2IndexValueMap.containsKey(elementId)) { - element2IndexValueMap.get(elementId).add(indexValue); - } else { - element2IndexValueMap.put(elementId, - Sets.newHashSet(indexValue)); - } - } - - public void selectedIndexField(Id indexField) { - this.selectedIndexField = indexField; - } - - public Set toRemoveIndexValues(Id indexField, Id elementId) { - if (!this.filed2IndexValues.containsKey(indexField)) { - return null; - } - return this.filed2IndexValues.get(indexField).get(elementId); - } - - public void addLeftIndex(Id elementId, Id indexField, - Set indexValues) { - LeftIndex leftIndex = new LeftIndex(indexValues, indexField); - if (this.leftIndexMap.containsKey(elementId)) { - this.leftIndexMap.get(elementId).add(leftIndex); - } else { - this.leftIndexMap.put(elementId, Sets.newHashSet(leftIndex)); - } - } - - public Set getLeftIndex(Id elementId) { - return this.leftIndexMap.get(elementId); - } - - public void removeElementLeftIndex(Id elementId) { - this.leftIndexMap.remove(elementId); - } - - public boolean checkRangeIndex(HugeElement element, Condition cond, - Map rangeIndexMatches) { - // Not UserpropRelation - if (!(cond instanceof Condition.UserpropRelation)) { - return true; - } - - Condition.UserpropRelation propRelation = - (Condition.UserpropRelation) cond; - Id propId = propRelation.key(); - Set fieldValues = this.toRemoveIndexValues(propId, - element.id()); - if (fieldValues == null) { - // Not range index - return true; - } - - if (rangeIndexMatches.containsKey(propId)) { - return rangeIndexMatches.get(propId); - } - - HugeProperty property = element.getProperty(propId); - if (property == null) { - // Property value has been deleted, so it's not matched - this.addLeftIndex(element.id(), propId, fieldValues); - return this.cacheRangeIndexMatch(rangeIndexMatches, propId, - false); - } - - /* - * NOTE: If removing successfully means there is correct index, - * else we should add left-index values to left index map to - * wait the left-index to be removed. - */ - boolean hasRightValue = removeFieldValue(fieldValues, - property.value()); - if (!fieldValues.isEmpty()) { - this.addLeftIndex(element.id(), propId, fieldValues); - } - - /* - * NOTE: When query by more than one range index field, - * if current field is not the selected one, it can only be used to - * determine whether the index values matched, can't determine - * the element is valid or not. - */ - if (this.selectedIndexField != null) { - hasRightValue = !propId.equals(this.selectedIndexField) || - hasRightValue; - } - - return this.cacheRangeIndexMatch(rangeIndexMatches, propId, - hasRightValue); - } - - private boolean cacheRangeIndexMatch(Map rangeIndexMatches, - Id propertyId, - boolean matched) { - rangeIndexMatches.put(propertyId, matched); - return matched; - } - - private static boolean removeFieldValue(Set values, - Object value) { - for (Object elem : values) { - if (numberEquals(elem, value)) { - values.remove(elem); - return true; - } - } - return false; - } - - private static boolean numberEquals(Object number1, Object number2) { - // Same class compare directly - if (number1.getClass().equals(number2.getClass())) { - return number1.equals(number2); - } - - // Otherwise convert to BigDecimal to make two numbers comparable - Number n1 = NumericUtil.convertToNumber(number1); - Number n2 = NumericUtil.convertToNumber(number2); - BigDecimal b1 = BigDecimal.valueOf(n1.doubleValue()); - BigDecimal b2 = BigDecimal.valueOf(n2.doubleValue()); - return b1.compareTo(b2) == 0; - } - } - - public static final class LeftIndex { - - private final Set indexFieldValues; - private final Id indexField; - - public LeftIndex(Set indexFieldValues, Id indexField) { - this.indexFieldValues = indexFieldValues; - this.indexField = indexField; - } - - public Set indexFieldValues() { - return this.indexFieldValues; - } - - public Id indexField() { - return this.indexField; - } - } - - public interface ResultsFilter { - - boolean test(HugeElement element); - } - - public byte[] bytes() { - String cqs = gson.toJson(this); - return cqs.getBytes(StandardCharsets.UTF_8); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java index 649f88e7b3..1cc91be0d1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java @@ -26,9 +26,12 @@ import java.util.Set; import java.util.stream.Collectors; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.Condition.SyspropRelation; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.Condition.SyspropRelation; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.InsertionOrderUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java index d8bce082c6..99c436b289 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java @@ -20,8 +20,10 @@ import java.util.Iterator; import java.util.List; -import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.tx.GraphTransaction; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.type.define.Directions; public class EdgesQueryIterator implements Iterator { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdQuery.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdQuery.java deleted file mode 100644 index f7a1c732b3..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdQuery.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.query; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.InsertionOrderUtil; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public class IdQuery extends Query { - - private static final List EMPTY_IDS = ImmutableList.of(); - - // The id(s) will be concated with `or` - private List ids = EMPTY_IDS; - private boolean mustSortByInput = true; - - public IdQuery(HugeType resultType) { - super(resultType); - } - - public IdQuery(HugeType resultType, Query originQuery) { - super(resultType, originQuery); - } - - public IdQuery(HugeType resultType, Set ids) { - this(resultType); - this.query(ids); - } - - public IdQuery(HugeType resultType, Id id) { - this(resultType); - this.query(id); - } - - public IdQuery(Query originQuery, Id id) { - this(originQuery.resultType(), originQuery); - this.query(id); - } - - public IdQuery(Query originQuery, Set ids) { - this(originQuery.resultType(), originQuery); - this.query(ids); - } - - public boolean mustSortByInput() { - return this.mustSortByInput; - } - - public void mustSortByInput(boolean mustSortedByInput) { - this.mustSortByInput = mustSortedByInput; - } - - @Override - public int idsSize() { - return this.ids.size(); - } - - @Override - public Collection ids() { - return Collections.unmodifiableList(this.ids); - } - - public void resetIds() { - this.ids = EMPTY_IDS; - } - - public IdQuery query(Id id) { - E.checkArgumentNotNull(id, "Query id can't be null"); - if (this.ids == EMPTY_IDS) { - this.ids = InsertionOrderUtil.newList(); - } - - int last = this.ids.size() - 1; - if (last >= 0 && id.equals(this.ids.get(last))) { - // The same id as the previous one, just ignore it - return this; - } - - this.ids.add(id); - this.checkCapacity(this.ids.size()); - return this; - } - - public IdQuery query(Set ids) { - for (Id id : ids) { - this.query(id); - } - return this; - } - - @Override - public boolean test(HugeElement element) { - return this.ids.contains(element.id()); - } - - @Override - public IdQuery copy() { - IdQuery query = (IdQuery) super.copy(); - query.ids = this.ids == EMPTY_IDS ? EMPTY_IDS : - InsertionOrderUtil.newList(this.ids); - return query; - } - - public static final class OneIdQuery extends IdQuery { - - private Id id; - - public OneIdQuery(HugeType resultType, Id id) { - super(resultType); - super.mustSortByInput = false; - this.id = id; - } - - public OneIdQuery(Query originQuery, Id id) { - super(originQuery.resultType(), originQuery); - super.mustSortByInput = false; - this.id = id; - } - - public Id id() { - return this.id; - } - - public void resetId(Id id) { - this.id = id; - } - - @Override - public int idsSize() { - return this.id == null ? 0 : 1; - } - - @Override - public Set ids() { - return this.id == null ? ImmutableSet.of() : - ImmutableSet.of(this.id); - } - - @Override - public void resetIds() { - this.id = null; - } - - @Override - public IdQuery query(Id id) { - E.checkArgumentNotNull(id, "Query id can't be null"); - this.id = id; - return this; - } - - @Override - public boolean test(HugeElement element) { - if (this.id == null) { - return true; - } - return this.id.equals(element.id()); - } - - @Override - public IdQuery copy() { - OneIdQuery query = (OneIdQuery) super.copy(); - assert this.id.equals(query.id); - return query; - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java deleted file mode 100644 index b8fc8e2964..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.query; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.exception.LimitExceedException; -import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.CollectionType; -import org.apache.hugegraph.type.define.HugeKeys; -import org.apache.hugegraph.util.CollectionUtil; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.InsertionOrderUtil; -import org.apache.hugegraph.util.collection.IdSet; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public class Query implements Cloneable { - - // TODO: we should better not use Long.Max as the unify limit number - public static final long NO_LIMIT = Long.MAX_VALUE; - - public static final long COMMIT_BATCH = 500L; - public static final long QUERY_BATCH = 100L; - - public static final long NO_CAPACITY = -1L; - public static final long DEFAULT_CAPACITY = 800000L; // HugeGraph-777 - - private static final ThreadLocal CAPACITY_CONTEXT = new ThreadLocal<>(); - - protected static final Query NONE = new Query(HugeType.UNKNOWN); - - private static final Set EMPTY_OLAP_PKS = ImmutableSet.of(); - - private HugeType resultType; - private Map orders; - private long offset; - private long actualOffset; - private long actualStoreOffset; - private long limit; - private long skipDegree; - private String page; - private long capacity; - private boolean showHidden; - private boolean showDeleting; - private boolean showExpired; - private boolean olap; - private boolean withProperties; - private OrderType orderType; - private Set olapPks; - - private Aggregate aggregate; - - private Query originQuery; - - public Query(HugeType resultType) { - this(resultType, null); - } - - public Query(HugeType resultType, Query originQuery) { - this.resultType = resultType; - this.originQuery = originQuery; - - this.orders = null; - - this.offset = 0L; - this.actualOffset = 0L; - this.actualStoreOffset = 0L; - this.limit = NO_LIMIT; - this.skipDegree = NO_LIMIT; - this.page = null; - - this.capacity = defaultCapacity(); - - this.showHidden = false; - this.showDeleting = false; - - this.withProperties = true; - this.orderType = OrderType.ORDER_STRICT; - - this.aggregate = null; - this.showExpired = false; - this.olap = false; - this.olapPks = EMPTY_OLAP_PKS; - } - - public void copyBasic(Query query) { - E.checkNotNull(query, "query"); - this.offset = query.offset(); - this.limit = query.limit(); - this.skipDegree = query.skipDegree(); - this.page = query.page(); - this.capacity = query.capacity(); - this.showHidden = query.showHidden(); - this.showDeleting = query.showDeleting(); - this.withProperties = query.withProperties(); - this.orderType = query.orderType(); - this.aggregate = query.aggregate(); - this.showExpired = query.showExpired(); - this.olap = query.olap(); - if (query.orders != null) { - this.orders(query.orders); - } - } - - public HugeType resultType() { - return this.resultType; - } - - public void resultType(HugeType resultType) { - this.resultType = resultType; - } - - public Query originQuery() { - return this.originQuery; - } - - public void setOriginQuery(Query query) { - this.originQuery = query; - } - - public Query rootOriginQuery() { - Query root = this; - while (root.originQuery != null) { - root = root.originQuery; - } - return root; - } - - protected void originQuery(Query originQuery) { - this.originQuery = originQuery; - } - - public Map orders() { - return Collections.unmodifiableMap(this.getOrNewOrders()); - } - - public void orders(Map orders) { - this.orders = InsertionOrderUtil.newMap(orders); - } - - public void order(HugeKeys key, Order order) { - this.getOrNewOrders().put(key, order); - } - - protected Map getOrNewOrders() { - if (this.orders != null) { - return this.orders; - } - this.orders = InsertionOrderUtil.newMap(); - return this.orders; - } - - public long offset() { - return this.offset; - } - - public void offset(long offset) { - if (offset < 0L) { - E.checkArgument(false, "Invalid offset %s", offset); - } - this.offset = offset; - } - - public void copyOffset(Query parent) { - assert this.offset == 0L || this.offset == parent.offset; - assert this.actualOffset == 0L || - this.actualOffset == parent.actualOffset; - this.offset = parent.offset; - this.actualOffset = parent.actualOffset; - } - - public long actualOffset() { - return this.actualOffset; - } - - public void resetActualOffset() { - this.actualOffset = 0L; - this.actualStoreOffset = 0L; - } - - public long goOffset(long offset) { - if (offset < 0L) { - E.checkArgument(false, "Invalid offset value: %s", offset); - } - if (this.originQuery != null) { - this.goParentOffset(offset); - } - return this.goSelfOffset(offset); - } - - private void goParentOffset(long offset) { - assert offset >= 0L; - Query parent = this.originQuery; - while (parent != null) { - parent.actualOffset += offset; - parent = parent.originQuery; - } - } - - private long goSelfOffset(long offset) { - assert offset >= 0L; - if (this.originQuery != null) { - this.originQuery.goStoreOffsetBySubQuery(offset); - } - this.actualOffset += offset; - return this.actualOffset; - } - - private long goStoreOffsetBySubQuery(long offset) { - Query parent = this.originQuery; - while (parent != null) { - parent.actualStoreOffset += offset; - parent = parent.originQuery; - } - this.actualStoreOffset += offset; - return this.actualStoreOffset; - } - - public Set skipOffsetIfNeeded(Set elems) { - /* - * Skip index(index query with offset) for performance optimization. - * We assume one result is returned by each index, but if there are - * overridden index it will cause confusing offset and results. - */ - long fromIndex = this.offset() - this.actualOffset(); - if (fromIndex < 0L) { - // Skipping offset is overhead, no need to skip - fromIndex = 0L; - } - // An index holder yields ids in batches, only count this batch's ids - fromIndex = Math.min(fromIndex, elems.size()); - if (fromIndex > 0L) { - this.goOffset(fromIndex); - } - - if (fromIndex >= elems.size()) { - return ImmutableSet.of(); - } - long toIndex = this.total(); - if (this.noLimit() || toIndex > elems.size()) { - toIndex = elems.size(); - } - if (fromIndex == 0L && toIndex == elems.size()) { - return elems; - } - assert fromIndex < elems.size(); - assert toIndex <= elems.size(); - return CollectionUtil.subSet(elems, (int) fromIndex, (int) toIndex); - } - - public long remaining() { - if (this.limit == NO_LIMIT) { - return NO_LIMIT; - } else { - return this.total() - this.actualOffset(); - } - } - - public long total() { - if (this.limit == NO_LIMIT) { - return NO_LIMIT; - } else { - return this.offset + this.limit; - } - } - - public long limit() { - if (this.capacity != NO_CAPACITY) { - if (this.limit == NO_LIMIT) { - /* - * TODO: may need to return this.capacity here. - * In most cases, capacity == DEFAULT_CAPACITY, then limit() - * will return NO_LIMIT, thus rely on Query.checkCapacity() - * to check in the next step. - */ - } - if (this.limit != NO_LIMIT && this.limit > this.capacity) { - E.checkArgument(false, - "Invalid limit %s, must be <= capacity(%s)", - this.limit, this.capacity); - } - } - return this.limit; - } - - public void limit(long limit) { - if (limit != NO_LIMIT && limit < 0L) { - E.checkArgument(false, "Invalid limit %s", limit); - } - this.limit = limit; - } - - public boolean noLimit() { - return this.limit() == NO_LIMIT; - } - - public boolean noLimitAndOffset() { - return this.limit() == NO_LIMIT && this.offset() == 0L; - } - - public boolean reachLimit(long count) { - long limit = this.limit(); - if (limit == NO_LIMIT) { - return false; - } - return count >= (limit + this.offset()); - } - - /** - * Set or update the offset and limit by a range [start, end) - * NOTE: it will use the min range one: max start and min end - * - * @param start the range start, include it - * @param end the range end, exclude it - */ - public long range(long start, long end) { - // Update offset - long offset = this.offset(); - start = Math.max(start, offset); - this.offset(start); - - // Update limit - if (end != -1L) { - if (!this.noLimit()) { - end = Math.min(end, offset + this.limit()); - } else { - assert end < Query.NO_LIMIT; - } - if (end < start) { - E.checkArgument(false, "Invalid range: [%s, %s)", start, end); - } - this.limit(end - start); - } else { - // Keep the origin limit - assert this.limit() <= Query.NO_LIMIT; - } - return this.limit; - } - - public String page() { - if (this.page != null) { - if (this.limit() == 0L) { - E.checkState(false, - "Can't set limit=0 when using paging"); - } - if (this.offset() != 0L) { - E.checkState(false, - "Can't set offset when using paging, but got '%s'", - this.offset()); - } - } - return this.page; - } - - public String pageWithoutCheck() { - return this.page; - } - - public void page(String page) { - this.page = page; - } - - public boolean paging() { - return this.page != null; - } - - public void olap(boolean olap) { - this.olap = olap; - } - - public boolean olap() { - return this.olap; - } - - public void olapPks(Set olapPks) { - for (Id olapPk : olapPks) { - this.olapPk(olapPk); - } - } - - public void olapPk(Id olapPk) { - if (this.olapPks == EMPTY_OLAP_PKS) { - this.olapPks = new IdSet(CollectionType.EC); - } - this.olapPks.add(olapPk); - } - - public Set olapPks() { - return this.olapPks; - } - - public long capacity() { - return this.capacity; - } - - public void capacity(long capacity) { - this.capacity = capacity; - } - - public boolean bigCapacity() { - return this.capacity == NO_CAPACITY || this.capacity > DEFAULT_CAPACITY; - } - - public void checkCapacity(long count) throws LimitExceedException { - // Throw LimitExceedException if reach capacity - if (this.capacity != NO_CAPACITY && count > this.capacity) { - final int MAX_CHARS = 256; - String query = this.toString(); - if (query.length() > MAX_CHARS) { - query = query.substring(0, MAX_CHARS) + "..."; - } - throw new LimitExceedException( - "Too many records(must <= %s) for the query: %s", - this.capacity, query); - } - } - - public Aggregate aggregate() { - return this.aggregate; - } - - public Aggregate aggregateNotNull() { - if (this.aggregate == null) { - E.checkArgument(false, - "The aggregate must be set for number query"); - } - return this.aggregate; - } - - public void aggregate(AggregateFunc func, String property) { - this.aggregate = new Aggregate(func, property); - } - - public void aggregate(Aggregate aggregate) { - this.aggregate = aggregate; - } - - public boolean showHidden() { - return this.showHidden; - } - - public void showHidden(boolean showHidden) { - this.showHidden = showHidden; - } - - public boolean showDeleting() { - return this.showDeleting; - } - - public void showDeleting(boolean showDeleting) { - this.showDeleting = showDeleting; - } - - public long skipDegree() { - return this.skipDegree; - } - - public void skipDegree(long skipDegree) { - this.skipDegree = skipDegree; - } - - public boolean withProperties() { - return this.withProperties; - } - - public void withProperties(boolean withProperties) { - this.withProperties = withProperties; - } - - public OrderType orderType() { - return this.orderType; - } - - public void orderType(OrderType orderType) { - this.orderType = orderType; - } - - public boolean showExpired() { - return this.showExpired; - } - - public void showExpired(boolean showExpired) { - this.showExpired = showExpired; - } - - public Collection ids() { - return ImmutableList.of(); - } - - public Collection conditions() { - return ImmutableList.of(); - } - - public int idsSize() { - return 0; - } - - public int conditionsSize() { - return 0; - } - - public boolean empty() { - return this.idsSize() == 0 && this.conditionsSize() == 0; - } - - public boolean test(HugeElement element) { - return true; - } - - public Query copy() { - try { - return (Query) this.clone(); - } catch (CloneNotSupportedException e) { - throw new BackendException(e); - } - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof Query)) { - return false; - } - Query other = (Query) object; - return this.resultType.equals(other.resultType) && - this.orders().equals(other.orders()) && - this.offset == other.offset && - this.limit == other.limit && - Objects.equals(this.page, other.page) && - this.ids().equals(other.ids()) && - this.conditions().equals(other.conditions()) && - this.withProperties == other.withProperties; - } - - @Override - public int hashCode() { - return this.resultType.hashCode() ^ - this.orders().hashCode() ^ - Long.hashCode(this.offset) ^ - Long.hashCode(this.limit) ^ - Objects.hashCode(this.page) ^ - this.ids().hashCode() ^ - this.conditions().hashCode() ^ - Boolean.hashCode(this.withProperties); - } - - @Override - public String toString() { - Map pairs = InsertionOrderUtil.newMap(); - if (this.page != null) { - pairs.put("page", String.format("'%s'", this.page)); - } - if (this.offset != 0) { - pairs.put("offset", this.offset); - } - if (this.limit != NO_LIMIT) { - pairs.put("limit", this.limit); - } - if (!this.orders().isEmpty()) { - pairs.put("order by", this.orders()); - } - - StringBuilder sb = new StringBuilder(128); - sb.append("`Query "); - if (this.aggregate != null) { - sb.append(this.aggregate); - } else { - sb.append('*'); - } - sb.append(" from ").append(this.resultType); - for (Map.Entry entry : pairs.entrySet()) { - sb.append(' ').append(entry.getKey()) - .append(' ').append(entry.getValue()).append(','); - } - if (!pairs.isEmpty()) { - // Delete last comma - sb.deleteCharAt(sb.length() - 1); - } - - if (!this.empty()) { - sb.append(" where"); - } - - // Append ids - if (!this.ids().isEmpty()) { - sb.append(" id in ").append(this.ids()); - } - - // Append conditions - if (!this.conditions().isEmpty()) { - if (!this.ids().isEmpty()) { - sb.append(" and"); - } - sb.append(" ").append(this.conditions()); - } - - sb.append('`'); - return sb.toString(); - } - - public static long defaultCapacity(long capacity) { - Long old = CAPACITY_CONTEXT.get(); - CAPACITY_CONTEXT.set(capacity); - return old != null ? old : DEFAULT_CAPACITY; - } - - public static long defaultCapacity() { - Long capacity = CAPACITY_CONTEXT.get(); - return capacity != null ? capacity : DEFAULT_CAPACITY; - } - - public static void checkForceCapacity(long count) throws LimitExceedException { - if (count > Query.DEFAULT_CAPACITY) { - throw new LimitExceedException( - "Too many records(must <= %s) for one query", - Query.DEFAULT_CAPACITY); - } - } - - public enum OrderType { - // Under batch interface, the requirement for return order - ORDER_NONE, // Allow unordered - ORDER_WITHIN_VERTEX, // Edges within a vertex will not be broken, but there is no order between different vertices. - ORDER_STRICT // Ensure the original input point order - } - - public enum Order { - ASC, - DESC - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryBatch.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryBatch.java index f210a503a2..58088a9263 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryBatch.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryBatch.java @@ -25,10 +25,11 @@ import java.util.function.BiPredicate; import java.util.function.Function; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.CIter; import org.apache.hugegraph.iterator.Metadatable; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.type.Idfiable; import org.apache.hugegraph.util.InsertionOrderUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResultContext.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResultContext.java index 27e6ec67ae..6392981e50 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResultContext.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResultContext.java @@ -21,9 +21,12 @@ import java.util.Collections; import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; -import org.apache.hugegraph.backend.query.ConditionQuery.ResultsFilter; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.ConditionQuery.ResultsFilter; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; /** Decisions captured for one batch; queries retain shared index cleanup data. */ public final class QueryResultContext { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResults.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResults.java index 35675bcf35..ce68722408 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResults.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/QueryResults.java @@ -25,17 +25,21 @@ import java.util.function.BiPredicate; import java.util.function.Function; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.query.QueryBatch.BatchIterator; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.CIter; import org.apache.hugegraph.iterator.ListIterator; import org.apache.hugegraph.perf.PerfUtil.Watched; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.Idfiable; /** A lazy stream of query batches. Only the final consumer flattens the stream. */ public class QueryResults { + private static final Query EMPTY_QUERY = new Query(HugeType.UNKNOWN); + private final BatchIterator> batches; private final Object metadata; private Iterator results; @@ -346,7 +350,7 @@ public static Iterator iterator(T value) { } public static QueryResults empty() { - return new QueryResults(QueryResults.emptyIterator(), Query.NONE); + return new QueryResults(QueryResults.emptyIterator(), EMPTY_QUERY); } public static Iterator emptyIterator() { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/AbstractSerializerAdapter.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/AbstractSerializerAdapter.java deleted file mode 100644 index 1a66ddf074..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/AbstractSerializerAdapter.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.backend.query.serializer; - -import java.lang.reflect.Type; -import java.util.Map; - -import org.apache.hugegraph.backend.BackendException; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -// TODO: optimize by binary protocol -public abstract class AbstractSerializerAdapter implements JsonSerializer, - JsonDeserializer { - - //Note: By overriding the method to get the mapping - public abstract Map validType(); - - @Override - public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws - JsonParseException { - JsonObject object = json.getAsJsonObject(); - String type = object.get("cls").getAsString(); - JsonElement element = object.get("el"); - try { - return context.deserialize(element, validType().get(type)); - } catch (Exception e) { - throw new BackendException("Unknown element type: " + type, e); - } - } - - /* - * Note: Currently, only the first character of the class name is taken as the key - * to reduce serialization results - * */ - @Override - public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject result = new JsonObject(); - Class clazz = src.getClass(); - result.add("cls", new JsonPrimitive(clazz.getSimpleName().substring(0, 1).toUpperCase())); - result.add("el", context.serialize(src, clazz)); - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryAdapter.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryAdapter.java deleted file mode 100644 index 47b7c76a00..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryAdapter.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.backend.query.serializer; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.type.define.Directions; - -import com.google.common.collect.ImmutableMap; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.reflect.TypeToken; - -public class QueryAdapter extends AbstractSerializerAdapter { - - static ImmutableMap cls = - ImmutableMap.builder() - // TODO: uncomment later - .put("N", Condition.Not.class) - .put("A", Condition.And.class) - .put("O", Condition.Or.class) - .put("S", Condition.SyspropRelation.class) - .put("U", Condition.UserpropRelation.class) - .build(); - - static boolean isPrimitive(Class clz) { - try { - return (clz == Date.class) || ((Class) clz.getField("TYPE").get(null)).isPrimitive(); - } catch (Exception e) { - return false; - } - } - - @Override - public Map validType() { - return cls; - } - - @Override - public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - Condition condition = super.deserialize(json, typeOfT, context); - if (condition instanceof Condition.Relation) { - JsonObject object = json.getAsJsonObject(); - if (object.has("el")) { - JsonElement elElement = object.get("el"); - JsonElement valueElement = elElement.getAsJsonObject().get("value"); - if (valueElement.isJsonObject()) { - String cls = valueElement.getAsJsonObject().get("cls").getAsString(); - try { - Class actualClass = Class.forName(cls); - Object obj = context.deserialize(valueElement, actualClass); - ((Condition.Relation) condition).value(obj); - } catch (ClassNotFoundException e) { - throw new JsonParseException(e.getMessage()); - } - } else if (elElement.getAsJsonObject().has("valuecls")) { - if (valueElement.isJsonArray()) { - String cls = elElement.getAsJsonObject().get("valuecls").getAsString(); - try { - Class actualClass = Class.forName(cls); - Type type = TypeToken.getParameterized(ArrayList.class, actualClass) - .getType(); - Object value = context.deserialize(valueElement, type); - ((Condition.Relation) condition).value(value); - } catch (ClassNotFoundException e) { - throw new JsonParseException(e.getMessage()); - } - } else { - String cls = elElement.getAsJsonObject().get("valuecls").getAsString(); - try { - Class actualClass = Class.forName(cls); - Object obj = context.deserialize(valueElement, actualClass); - ((Condition.Relation) condition).value(obj); - } catch (ClassNotFoundException e) { - throw new JsonParseException(e.getMessage()); - } - } - - } else if (valueElement.isJsonPrimitive() && - valueElement.getAsJsonPrimitive().isString()) { - switch ((String) ((Condition.Relation) condition).value()) { - case "OUT": - ((Condition.Relation) condition).value(Directions.OUT); - break; - case "IN": - ((Condition.Relation) condition).value(Directions.IN); - break; - default: - break; - } - } - } - } - return condition; - } - - @Override - public JsonElement serialize(Condition src, Type typeOfSrc, JsonSerializationContext context) { - JsonElement result = super.serialize(src, typeOfSrc, context); - if (src instanceof Condition.Relation) { - JsonObject object = result.getAsJsonObject(); - JsonElement valueElement = object.get("el").getAsJsonObject().get("value"); - if (valueElement.isJsonObject()) { - valueElement.getAsJsonObject() - .add("cls", - new JsonPrimitive( - ((Condition.Relation) src).value().getClass().getName())); - } else if (isPrimitive(((Condition.Relation) src).value().getClass())) { - object.get("el").getAsJsonObject() - .add("valuecls", - new JsonPrimitive( - ((Condition.Relation) src).value().getClass().getName())); - } else if (valueElement.isJsonArray()) { - if (((Condition.Relation) src).value() instanceof List) { - String valueCls = - ((List) ((Condition.Relation) src).value()).get(0).getClass().getName(); - object.get("el").getAsJsonObject().add("valuecls", new JsonPrimitive(valueCls)); - } - } - } - return result; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryIdAdapter.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryIdAdapter.java deleted file mode 100644 index e7ebaea766..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/serializer/QueryIdAdapter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.backend.query.serializer; - -import java.lang.reflect.Type; -import java.util.Map; - -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; - -import com.google.common.collect.ImmutableMap; - -public class QueryIdAdapter extends AbstractSerializerAdapter { - - static ImmutableMap cls = - ImmutableMap.builder() - .put("E", EdgeId.class) - .put("S", IdGenerator.StringId.class) - .put("L", IdGenerator.LongId.class) - .put("U", IdGenerator.UuidId.class) - .put("O", IdGenerator.ObjectId.class) - .put("B", BinaryBackendEntry.BinaryId.class) - .build(); - - @Override - public Map validType() { - return cls; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/AbstractSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/AbstractSerializer.java index 734cb90426..ce79e5b5aa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/AbstractSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/AbstractSerializer.java @@ -18,11 +18,11 @@ package org.apache.hugegraph.backend.serializer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.iterator.CIter; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java index 9dfb8b4e5c..50b8b4436d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java @@ -17,19 +17,20 @@ package org.apache.hugegraph.backend.serializer; -import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.backend.BinaryId; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendEntryIterator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.Bytes; public class BinaryBackendEntry implements BackendEntry { @@ -207,79 +208,4 @@ public boolean equals(Object obj) { public int hashCode() { return this.id().hashCode() ^ this.columns.size(); } - - public static class BinaryId implements Id { - - protected byte[] bytes; - protected Id id; - - public BinaryId(byte[] bytes, Id id) { - this.bytes = bytes; - this.id = id; - } - - public Id origin() { - return this.id; - } - - @Override - public IdType type() { - return IdType.UNKNOWN; - } - - @Override - public Object asObject() { - return ByteBuffer.wrap(this.bytes); - } - - @Override - public String asString() { - throw new UnsupportedOperationException(); - } - - @Override - public long asLong() { - throw new UnsupportedOperationException(); - } - - @Override - public int compareTo(Id other) { - return Bytes.compare(this.bytes, other.asBytes()); - } - - @Override - public byte[] asBytes() { - return this.bytes; - } - - public byte[] asBytes(int offset) { - E.checkArgument(offset < this.bytes.length, - "Invalid offset %s, must be < length %s", - offset, this.bytes.length); - return Arrays.copyOfRange(this.bytes, offset, this.bytes.length); - } - - @Override - public int length() { - return this.bytes.length; - } - - @Override - public int hashCode() { - return ByteBuffer.wrap(this.bytes).hashCode(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof BinaryId)) { - return false; - } - return Arrays.equals(this.bytes, ((BinaryId) other).bytes); - } - - @Override - public String toString() { - return "0x" + Bytes.toHex(this.bytes); - } - } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryEntryIterator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryEntryIterator.java index 1095742681..a499ffa00c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryEntryIterator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryEntryIterator.java @@ -20,7 +20,7 @@ import java.util.function.BiFunction; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendEntry.BackendIterator; import org.apache.hugegraph.backend.store.BackendEntryIterator; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryScatterSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryScatterSerializer.java index 18b642a001..f69fd703cb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryScatterSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryScatterSerializer.java @@ -17,13 +17,15 @@ package org.apache.hugegraph.backend.serializer; +import org.apache.hugegraph.serializer.BytesBuffer; + import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.structure.HugeVertexProperty; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java index 0bb07760a5..445d028cf7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java @@ -17,7 +17,10 @@ package org.apache.hugegraph.backend.serializer; -import static org.apache.hugegraph.schema.SchemaElement.UNDEF; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer.IndexColumnName; +import org.apache.hugegraph.serializer.BytesBuffer.IndexExpiryLayout; +import org.apache.hugegraph.serializer.BinaryElementSerializer; import java.util.Arrays; import java.util.Collection; @@ -27,32 +30,32 @@ import org.apache.commons.lang.NotImplementedException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.RangeConditions; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.serializer.BinaryBackendEntry.BinaryId; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.RangeConditions; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.backend.BinaryId; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.iterator.CIter; import org.apache.hugegraph.iterator.MapperIterator; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.structure.HugeProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.structure.HugeVertexProperty; @@ -61,7 +64,6 @@ import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; import org.apache.hugegraph.type.define.Directions; -import org.apache.hugegraph.type.define.EdgeLabelType; import org.apache.hugegraph.type.define.Frequency; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.type.define.IdStrategy; @@ -198,137 +200,55 @@ protected byte[] formatPropertyName(HugeProperty prop) { protected BackendColumn formatProperty(HugeProperty prop) { BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_PROPERTY); - buffer.writeProperty(prop.propertyKey(), prop.value()); + buffer.writeSchemaProperty(prop.propertyKey(), prop.value()); return BackendColumn.of(this.formatPropertyName(prop), buffer.bytes()); } protected void parseProperty(Id pkeyId, BytesBuffer buffer, HugeElement owner) { - PropertyKey pkey = owner.graph().propertyKey(pkeyId); - - // Parse value - Object value = buffer.readProperty(pkey); - - // Set properties of vertex/edge - if (pkey.cardinality() == Cardinality.SINGLE) { - owner.addProperty(pkey, value); - } else { - if (!(value instanceof Collection)) { - throw new BackendException( - "Invalid value of non-single property: %s", value); - } - owner.addProperty(pkey, value); - } + BinaryElementSerializer.getInstance().parseSchemaProperty( + owner.graph(), pkeyId, buffer, owner::addProperty); } - protected void formatProperties(Collection> props, - BytesBuffer buffer) { - // Write properties size - buffer.writeVInt(props.size()); - - // Write properties data - for (HugeProperty property : props) { - PropertyKey pkey = property.propertyKey(); - buffer.writeVInt(SchemaElement.schemaId(pkey.id())); - buffer.writeProperty(pkey, property.value()); - } + protected void formatProperties(HugeElement owner, BytesBuffer buffer) { + BinaryElementSerializer.getInstance().formatSchemaProperties(owner.element(), buffer); } protected void parseProperties(BytesBuffer buffer, HugeElement owner) { - int size = buffer.readVInt(); - assert size >= 0; - for (int i = 0; i < size; i++) { - Id pkeyId = IdGenerator.of(buffer.readVInt()); - this.parseProperty(pkeyId, buffer, owner); - } + BinaryElementSerializer.getInstance().parseSchemaProperties( + owner.graph(), buffer, owner::addProperty); } protected void formatExpiredTime(long expiredTime, BytesBuffer buffer) { - buffer.writeVLong(expiredTime); + BinaryElementSerializer.getInstance().formatExpiredTime(expiredTime, buffer); } protected void parseExpiredTime(BytesBuffer buffer, HugeElement element) { - element.expiredTime(buffer.readVLong()); + BinaryElementSerializer.getInstance().parseExpiredTime(buffer, element.element()); } protected byte[] formatEdgeValue(HugeEdge edge) { - int propsCount = edge.sizeOfProperties(); - BytesBuffer buffer = BytesBuffer.allocate(4 + 16 * propsCount); - - // Write edge id - //buffer.writeId(edge.id()); - - // Write edge properties - this.formatProperties(edge.getProperties(), buffer); - - // Write edge expired time if needed - if (edge.hasTtl()) { - this.formatExpiredTime(edge.expiredTime(), buffer); - } - - return buffer.bytes(); + return BinaryElementSerializer.getInstance().formatSchemaEdgeValue(edge.element()); } protected void parseEdge(BackendColumn col, HugeVertex vertex, HugeGraph graph) { - // owner-vertex + dir + edge-label + sort-values + other-vertex - - BytesBuffer buffer = BytesBuffer.wrap(col.name); - if (this.keyWithIdPrefix) { - // Consume owner-vertex id - buffer.readId(); - } - byte type = buffer.read(); - Id labelId = buffer.readId(); - Id subLabelId = buffer.readId(); - String sortValues = buffer.readStringWithEnding(); - Id otherVertexId = buffer.readId(); - - boolean direction = EdgeId.isOutDirectionFromCode(type); - - HugeEdge edge; - if (graph == null) { /* when calculation sinking */ - EdgeLabel edgeLabel = new EdgeLabel(null, subLabelId, UNDEF); - if (subLabelId != labelId) { - edgeLabel.edgeLabelType(EdgeLabelType.SUB); - edgeLabel.fatherId(labelId); - } - edge = HugeEdge.constructEdgeWithoutGraph(vertex, direction, edgeLabel, - sortValues, otherVertexId); - } else { - EdgeLabel edgeLabel = graph.edgeLabelOrNone(subLabelId); - edge = HugeEdge.constructEdge(vertex, direction, edgeLabel, - sortValues, otherVertexId); - } - - // Parse edge-id + edge-properties - buffer = BytesBuffer.wrap(col.value); - - //Id id = buffer.readId(); - - // Parse edge properties - this.parseProperties(buffer, edge); - - // Parse edge expired time if needed - if (edge.hasTtl()) { - this.parseExpiredTime(buffer, edge); - } + EdgeId id = BytesBuffer.wrap(col.name).readEdgeId(this.keyWithIdPrefix, vertex.id()); + EdgeLabel edgeLabel = BinaryElementSerializer.getInstance().edgeLabel(graph, id, vertex.graph()); + boolean direction = id.direction() == Directions.OUT; + HugeEdge edge = graph == null ? + HugeEdge.constructEdgeWithoutGraph(vertex, direction, edgeLabel, + id.sortValues(), id.otherVertexId()) : + HugeEdge.constructEdge(vertex, direction, edgeLabel, + id.sortValues(), id.otherVertexId()); + + BinaryElementSerializer.getInstance().parseSchemaEdgeValue( + edge.graph(), col.value, edge.element(), edge::addProperty); } protected void parseVertex(byte[] value, HugeVertex vertex) { - BytesBuffer buffer = BytesBuffer.wrap(value); - - // Parse vertex label - VertexLabel label = vertex.graph().vertexLabelOrNone(buffer.readId()); - vertex.correctVertexLabel(label); - - // Parse properties - this.parseProperties(buffer, vertex); - - // Parse vertex expired time if needed - if (vertex.hasTtl()) { - this.parseExpiredTime(buffer, vertex); - } + BinaryElementSerializer.getInstance().parseSchemaVertexValue( + vertex.graph(), value, vertex.element(), vertex::addProperty); } protected void parseColumn(BackendColumn col, HugeVertex vertex) { @@ -357,48 +277,32 @@ else if (type == HugeType.SYS_PROPERTY.code()) { } } - protected byte[] formatIndexName(HugeIndex index) { - BytesBuffer buffer; - Id elemId = index.elementId(); - if (!this.indexWithIdPrefix) { - int idLen = 1 + elemId.length(); - buffer = BytesBuffer.allocate(idLen); - } else { - Id indexId = index.id(); - HugeType type = index.type(); - if (!type.isNumericIndex() && indexIdLengthExceedLimit(indexId)) { - indexId = index.hashId(); - } - int idLen = 1 + elemId.length() + 1 + indexId.length(); - buffer = BytesBuffer.allocate(idLen); - // Write index-id - buffer.writeIndexId(indexId, type); - } - // Write element-id - buffer.writeId(elemId); - // Write expired time if needed - if (index.hasTtl()) { - buffer.writeVLong(index.expiredTime()); - } - - return buffer.bytes(); + protected byte[] formatIndexName(Index index) { + return BinaryElementSerializer.getInstance().formatSchemaIndex( + index.type(), index.indexLabelId(), index.fieldValues(), index.elementId(), + this.indexWithIdPrefix, index.hasTtl(), index.expiredTime()).name; } protected void parseIndexName(HugeGraph graph, ConditionQuery query, BinaryBackendEntry entry, - HugeIndex index, Object fieldValues) { + Index index, Object fieldValues) { for (BackendColumn col : entry.columns()) { - if (indexFieldValuesUnmatched(col.value, fieldValues)) { - // Skip if field-values is not matched (just the same hash) + if (!index.type().isLabelIndex() && indexFieldValuesUnmatched(col.value, fieldValues)) { + // User-index hash collision filtering remains an engine adapter. continue; } BytesBuffer buffer = BytesBuffer.wrap(col.name); - if (this.indexWithIdPrefix) { - buffer.readIndexId(index.type()); + IndexColumnName name = buffer.readIndexColumnName( + index.type(), this.indexWithIdPrefix, + index.hasTtl() ? IndexExpiryLayout.REQUIRED : IndexExpiryLayout.NONE); + Long storedLabelExpiry = BinaryElementSerializer.getInstance().storedLabelIndexExpiredTime( + index.type(), buffer.remaining() == 0, col.value); + if (index.type().isLabelIndex() && storedLabelExpiry == null && + indexFieldValuesUnmatched(col.value, fieldValues)) { + continue; } - Id elemId = buffer.readId(); - long expiredTime = index.hasTtl() ? buffer.readVLong() : 0L; - index.elementIds(elemId, expiredTime); + index.elementIds(name.elementId(), storedLabelExpiry == null ? + name.expiredTime() : storedLabelExpiry); } } @@ -414,25 +318,15 @@ public BackendEntry writeVertex(HugeVertex vertex) { return entry; } - int propsCount = vertex.sizeOfProperties(); - BytesBuffer buffer = BytesBuffer.allocate(8 + 16 * propsCount); - - // Write vertex label - buffer.writeId(vertex.schemaLabel().id()); - - // Write all properties of the vertex - this.formatProperties(vertex.getProperties(), buffer); - - // Write vertex expired time if needed + byte[] value = BinaryElementSerializer.getInstance().formatSchemaVertexValue(vertex.element()); if (vertex.hasTtl()) { entry.ttl(vertex.ttl()); - this.formatExpiredTime(vertex.expiredTime(), buffer); } - // Fill column + // Backend-specific column keys and entry TTL remain in the adapter. byte[] name = this.keyWithIdPrefix ? entry.id().asBytes() : BytesBuffer.BYTES_EMPTY; - entry.column(name, buffer.bytes()); + entry.column(name, value); return entry; } @@ -451,8 +345,7 @@ public BackendEntry writeOlapVertex(HugeVertex vertex) { } HugeProperty property = properties.iterator().next(); PropertyKey propertyKey = property.propertyKey(); - buffer.writeVInt(SchemaElement.schemaId(propertyKey.id())); - buffer.writeProperty(propertyKey, property.value()); + BinaryElementSerializer.getInstance().formatSchemaProperty(property.baseProperty(), buffer); // Fill column byte[] name = this.keyWithIdPrefix ? @@ -504,9 +397,8 @@ public HugeVertex readVertex(HugeGraph graph, BackendEntry bytesEntry) { } protected void parseVertexOlap(byte[] value, HugeVertex vertex) { - BytesBuffer buffer = BytesBuffer.wrap(value); - Id pkeyId = IdGenerator.of(buffer.readVInt()); - this.parseProperty(pkeyId, buffer, vertex); + BinaryElementSerializer.getInstance().parseSchemaPropertyRecord( + vertex.graph(), BytesBuffer.wrap(value), vertex::addProperty); } @Override @@ -576,7 +468,7 @@ public CIter readEdges(HugeGraph graph, BackendEntry bytesEntry) { } @Override - public BackendEntry writeIndex(HugeIndex index) { + public BackendEntry writeIndex(Index index) { BinaryBackendEntry entry; if (index.fieldValues() == null && index.elementIds().isEmpty()) { /* @@ -586,20 +478,17 @@ public BackendEntry writeIndex(HugeIndex index) { */ entry = this.formatILDeletion(index); } else { - Id id = index.id(); HugeType type = index.type(); - byte[] value = null; - if (!type.isNumericIndex() && indexIdLengthExceedLimit(id)) { - id = index.hashId(); - // Save field-values as column value if the key is a hash string - value = StringEncoding.encode(index.fieldValues().toString()); - } - + Id id = BinaryElementSerializer.schemaIndexId(type, index.indexLabelId(), index.fieldValues()); + BackendColumn column = + BinaryElementSerializer.getInstance().formatSchemaIndex( + type, index.indexLabelId(), index.fieldValues(), index.elementId(), + this.indexWithIdPrefix, index.hasTtl(), index.expiredTime()); entry = newBackendEntry(type, id); if (index.indexLabel().olap()) { entry.olap(true); } - entry.column(this.formatIndexName(index), value); + entry.columns(column); entry.subId(index.elementId()); if (index.hasTtl()) { @@ -610,7 +499,7 @@ public BackendEntry writeIndex(HugeIndex index) { } @Override - public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, + public Index readIndex(HugeGraph graph, ConditionQuery query, BackendEntry bytesEntry) { if (bytesEntry == null) { return null; @@ -619,7 +508,7 @@ public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, BinaryBackendEntry entry = this.convertEntry(bytesEntry); // NOTE: index id without length prefix byte[] bytes = entry.id().asBytes(); - HugeIndex index = HugeIndex.parseIndexId(graph, entry.type(), bytes); + Index index = Index.parseIndexId(graph, entry.type(), bytes); Object fieldValues = null; if (!index.type().isRangeIndex()) { @@ -871,7 +760,7 @@ private Query writeRangeIndexQuery(ConditionQuery query) { return new IdRangeQuery(query, start, keyMinEq, max, keyMaxEq); } - private BinaryBackendEntry formatILDeletion(HugeIndex index) { + private BinaryBackendEntry formatILDeletion(Index index) { Id id = index.indexLabelId(); BinaryId bid = new BinaryId(id.asBytes(), id); BinaryBackendEntry entry = new BinaryBackendEntry(index.type(), bid); @@ -967,17 +856,14 @@ protected static BinaryId formatIndexId(HugeType type, Id indexLabel, Object fieldValues, boolean equal) { boolean withEnding = type.isRangeIndex() || equal; - Id id = HugeIndex.formatIndexId(type, indexLabel, fieldValues); - if (!type.isNumericIndex() && indexIdLengthExceedLimit(id)) { - id = HugeIndex.formatIndexHashId(type, indexLabel, fieldValues); - } + Id id = BinaryElementSerializer.schemaIndexId(type, indexLabel, fieldValues); BytesBuffer buffer = BytesBuffer.allocate(1 + id.length()); byte[] idBytes = buffer.writeIndexId(id, type, withEnding).bytes(); return new BinaryId(idBytes, id); } protected static boolean indexIdLengthExceedLimit(Id id) { - return id.asBytes().length > BytesBuffer.INDEX_HASH_ID_THRESHOLD; + return BinaryElementSerializer.indexIdLengthExceedLimit(id); } protected static boolean indexFieldValuesUnmatched(byte[] value, diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java deleted file mode 100644 index faf1508299..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.serializer; - -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.UUID; - -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.serializer.BinaryBackendEntry.BinaryId; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.Cardinality; -import org.apache.hugegraph.type.define.DataType; -import org.apache.hugegraph.util.Blob; -import org.apache.hugegraph.util.Bytes; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.KryoUtil; -import org.apache.hugegraph.util.StringEncoding; - -/** - * class BytesBuffer is a util for read/write binary - */ -public final class BytesBuffer extends OutputStream { - - public static final int BYTE_LEN = Byte.BYTES; - public static final int SHORT_LEN = Short.BYTES; - public static final int INT_LEN = Integer.BYTES; - public static final int LONG_LEN = Long.BYTES; - public static final int CHAR_LEN = Character.BYTES; - public static final int FLOAT_LEN = Float.BYTES; - public static final int DOUBLE_LEN = Double.BYTES; - public static final int BYTES_LEN = 4; - public static final int BLOB_LEN = 5; - - public static final int UINT8_MAX = ((byte) -1) & 0xff; - public static final int UINT16_MAX = ((short) -1) & 0xffff; - public static final long UINT32_MAX = (-1) & 0xffffffffL; - - // TODO: support user-defined configuration - // NOTE: +1 to let code 0 represent length 1 - public static final int ID_LEN_MAX = 0x3fff + 1; // 16KB - public static final int EID_LEN_MAX = 64 * 1024; - - public static final byte STRING_ENDING_BYTE = (byte) 0x00; - public static final byte STRING_ENDING_BYTE_FF = (byte) 0xff; - - // TODO: support user-defined configuration - public static final long BYTES_LEN_MAX = 10 * Bytes.MB; - public static final long BLOB_LEN_MAX = 1 * Bytes.GB; - - public static final int MAX_PROPERTIES = BytesBuffer.UINT16_MAX; - - // The value must be in range [8, ID_LEN_MAX] - public static final int INDEX_HASH_ID_THRESHOLD = 32; - - public static final int DEFAULT_CAPACITY = 64; - public static final int MAX_BUFFER_CAPACITY = 128 * 1024 * 1024; // 128M - public static final int MAX_BUFFER_CAPACITY_UPPER_BOUND = (int) Bytes.GB; - - public static final int BUF_EDGE_ID = 128; - public static final int BUF_PROPERTY = 64; - - public static final byte[] BYTES_EMPTY = new byte[0]; - - private static volatile Integer maxBufferCapacity; - - private ByteBuffer buffer; - private final boolean resize; - - public BytesBuffer() { - this(DEFAULT_CAPACITY); - } - - public BytesBuffer(int capacity) { - int maxCapacity = maxBufferCapacity(); - if (capacity > maxCapacity) { - E.checkArgument(false, - "Capacity %s exceeds max buffer capacity: %s", - capacity, maxCapacity); - } - this.buffer = ByteBuffer.allocate(capacity); - this.resize = true; - } - - public BytesBuffer(ByteBuffer buffer) { - E.checkNotNull(buffer, "buffer"); - this.buffer = buffer; - this.resize = false; - } - - public static BytesBuffer allocate(int capacity) { - return new BytesBuffer(capacity); - } - - public static BytesBuffer wrap(ByteBuffer buffer) { - return new BytesBuffer(buffer); - } - - public static BytesBuffer wrap(byte[] array) { - return new BytesBuffer(ByteBuffer.wrap(array)); - } - - public static BytesBuffer wrap(byte[] array, int offset, int length) { - return new BytesBuffer(ByteBuffer.wrap(array, offset, length)); - } - - public static int maxBufferCapacity() { - Integer capacity = maxBufferCapacity; - return capacity != null ? capacity : MAX_BUFFER_CAPACITY; - } - - public static synchronized void initMaxBufferCapacity(int capacity) { - initMaxBufferCapacity(capacity, true); - } - - public static synchronized void initMaxBufferCapacity(int capacity, - boolean explicit) { - E.checkArgument(capacity >= DEFAULT_CAPACITY && - capacity <= MAX_BUFFER_CAPACITY_UPPER_BOUND, - "Max buffer capacity must be in range [%s, %s], " + - "but got %s", - DEFAULT_CAPACITY, MAX_BUFFER_CAPACITY_UPPER_BOUND, - capacity); - - if (!explicit) { - return; - } - - if (maxBufferCapacity == null) { - maxBufferCapacity = capacity; - return; - } - - if (maxBufferCapacity == capacity) { - return; - } - - throw new IllegalArgumentException(String.format( - "The process-wide serializer buffer max capacity has been " + - "initialized to %s, but got conflicting value %s", - maxBufferCapacity, capacity)); - } - - public ByteBuffer asByteBuffer() { - return this.buffer; - } - - public BytesBuffer forReadWritten() { - this.buffer.flip(); - return this; - } - - public BytesBuffer forReadAll() { - this.buffer.position(this.buffer.limit()); - return this; - } - - public byte[] array() { - return this.buffer.array(); - } - - public byte[] bytes() { - byte[] bytes = this.buffer.array(); - int position = this.buffer.position(); - if (position == bytes.length) { - return bytes; - } else { - return Arrays.copyOf(bytes, position); - } - } - - public int position() { - return this.buffer.position(); - } - - public BytesBuffer copyFrom(BytesBuffer other) { - this.write(other.bytes()); - return this; - } - - public int remaining() { - return this.buffer.remaining(); - } - - private void require(int size) { - // Does need to resize? - if (this.buffer.remaining() >= size) { - return; - } - // Can't resize for wrapped buffer since will change the origin ref - if (!this.resize) { - E.checkState(false, "Can't resize for wrapped buffer"); - } - - int maxCapacity = maxBufferCapacity(); - long requiredCapacity = (long) this.buffer.position() + size; - if (requiredCapacity > maxCapacity) { - E.checkArgument(false, - "Capacity %s exceeds max buffer capacity: %s", - requiredCapacity, maxCapacity); - } - - // Extra capacity as buffer - long newCapacity = Math.min(requiredCapacity + DEFAULT_CAPACITY, - maxCapacity); - ByteBuffer newBuffer = ByteBuffer.allocate((int) newCapacity); - this.buffer.flip(); - newBuffer.put(this.buffer); - this.buffer = newBuffer; - } - - public BytesBuffer write(byte val) { - require(BYTE_LEN); - this.buffer.put(val); - return this; - } - - @Override - public void write(int val) { - assert val <= UINT8_MAX; - require(BYTE_LEN); - this.buffer.put((byte) val); - } - - @Override - public void write(byte[] val) { - require(BYTE_LEN * val.length); - this.buffer.put(val); - } - - @Override - public void write(byte[] val, int offset, int length) { - require(BYTE_LEN * length); - this.buffer.put(val, offset, length); - } - - public BytesBuffer writeBoolean(boolean val) { - this.write(val ? 1 : 0); - return this; - } - - public BytesBuffer writeChar(char val) { - require(CHAR_LEN); - this.buffer.putChar(val); - return this; - } - - public BytesBuffer writeShort(short val) { - require(SHORT_LEN); - this.buffer.putShort(val); - return this; - } - - public BytesBuffer writeInt(int val) { - require(INT_LEN); - this.buffer.putInt(val); - return this; - } - - public BytesBuffer writeLong(long val) { - require(LONG_LEN); - this.buffer.putLong(val); - return this; - } - - public BytesBuffer writeFloat(float val) { - require(FLOAT_LEN); - this.buffer.putFloat(val); - return this; - } - - public BytesBuffer writeDouble(double val) { - require(DOUBLE_LEN); - this.buffer.putDouble(val); - return this; - } - - public byte peek() { - return this.buffer.get(this.buffer.position()); - } - - public byte peekLast() { - return this.buffer.get(this.buffer.limit() - 1); - } - - public byte read() { - return this.buffer.get(); - } - - public byte[] read(int length) { - byte[] bytes = new byte[length]; - this.buffer.get(bytes); - return bytes; - } - - public boolean readBoolean() { - return this.buffer.get() != 0; - } - - public char readChar() { - return this.buffer.getChar(); - } - - public short readShort() { - return this.buffer.getShort(); - } - - public int readInt() { - return this.buffer.getInt(); - } - - public long readLong() { - return this.buffer.getLong(); - } - - public float readFloat() { - return this.buffer.getFloat(); - } - - public double readDouble() { - return this.buffer.getDouble(); - } - - public BytesBuffer writeBytes(byte[] bytes) { - if (bytes.length > BYTES_LEN_MAX) { - E.checkArgument(false, - "The max length of bytes is %s, but got %s", - BYTES_LEN_MAX, bytes.length); - } - require(BYTES_LEN + bytes.length); - this.writeVInt(bytes.length); - this.write(bytes); - return this; - } - - public byte[] readBytes() { - int length = this.readVInt(); - assert length >= 0; - return this.read(length); - } - - public BytesBuffer writeBigBytes(byte[] bytes) { - if (bytes.length > BLOB_LEN_MAX) { - E.checkArgument(false, - "The max length of bytes is %s, but got %s", - BLOB_LEN_MAX, bytes.length); - } - require(BLOB_LEN + bytes.length); - this.writeVInt(bytes.length); - this.write(bytes); - return this; - } - - public byte[] readBigBytes() { - int length = this.readVInt(); - assert length >= 0; - return this.read(length); - } - - public BytesBuffer writeStringRaw(String val) { - this.write(StringEncoding.encode(val)); - return this; - } - - public BytesBuffer writeString(String val) { - byte[] bytes = StringEncoding.encode(val); - this.writeBytes(bytes); - return this; - } - - public String readString() { - return StringEncoding.decode(this.readBytes()); - } - - public BytesBuffer writeStringWithEnding(String value) { - if (!value.isEmpty()) { - byte[] bytes = StringEncoding.encode(value); - /* - * assert '0x00'/'0xFF' not exist in string index id - * NOTE: - * 0x00 is NULL in UTF8(or ASCII) bytes - * 0xFF is not a valid byte in UTF8 bytes - */ - assert !Bytes.contains(bytes, STRING_ENDING_BYTE_FF) : - "Invalid UTF8 bytes: " + value; - if (Bytes.contains(bytes, STRING_ENDING_BYTE)) { - E.checkArgument(false, "Can't contains byte '0x00' in string: '%s'", value); - } - this.write(bytes); - } - /* - * Choose 0x00 as ending symbol (see #1057) - * The following is out of date: - * A reasonable ending symbol should be 0x00(to ensure order), but - * considering that some backends like PG do not support 0x00 string, - * so choose 0xFF currently. - */ - this.write(STRING_ENDING_BYTE); - return this; - } - - public String readStringWithEnding() { - return StringEncoding.decode(this.readBytesWithEnding()); - } - - public BytesBuffer writeStringToRemaining(String value) { - byte[] bytes = StringEncoding.encode(value); - this.write(bytes); - return this; - } - - public String readStringFromRemaining() { - byte[] bytes = new byte[this.buffer.remaining()]; - this.buffer.get(bytes); - return StringEncoding.decode(bytes); - } - - public BytesBuffer writeUInt8(int val) { - assert val <= UINT8_MAX; - this.write(val); - return this; - } - - public int readUInt8() { - return this.read() & 0x000000ff; - } - - public BytesBuffer writeUInt16(int val) { - assert val <= UINT16_MAX; - this.writeShort((short) val); - return this; - } - - public int readUInt16() { - return this.readShort() & 0x0000ffff; - } - - public BytesBuffer writeUInt32(long val) { - assert val <= UINT32_MAX; - this.writeInt((int) val); - return this; - } - - public long readUInt32() { - return this.readInt() & 0xffffffffL; - } - - public BytesBuffer writeVInt(int value) { - // NOTE: negative numbers are not compressed - if (value > 0x0fffffff || value < 0) { - this.write(0x80 | ((value >>> 28) & 0x7f)); - } - if (value > 0x1fffff || value < 0) { - this.write(0x80 | ((value >>> 21) & 0x7f)); - } - if (value > 0x3fff || value < 0) { - this.write(0x80 | ((value >>> 14) & 0x7f)); - } - if (value > 0x7f || value < 0) { - this.write(0x80 | ((value >>> 7) & 0x7f)); - } - this.write(value & 0x7f); - - return this; - } - - public int readVInt() { - byte leading = this.read(); - if (leading == 0x80) { - E.checkArgument(false, - "Unexpected varint with leading byte '0x%s'", - Bytes.toHex(leading)); - } - int value = leading & 0x7f; - if (leading >= 0) { - assert (leading & 0x80) == 0; - return value; - } - - int i = 1; - for (; i < 5; i++) { - byte b = this.read(); - if (b >= 0) { - value = b | (value << 7); - break; - } else { - value = (b & 0x7f) | (value << 7); - } - } - - if (i >= 5) { - E.checkArgument(false, - "Unexpected varint %s with too many bytes(%s)", - value, i + 1); - } - if (i >= 4 && (leading & 0x70) != 0) { - E.checkArgument(false, - "Unexpected varint %s with leading byte '0x%s'", - value, Bytes.toHex(leading)); - } - return value; - } - - public BytesBuffer writeVLong(long value) { - if (value < 0) { - this.write((byte) 0x81); - } - if (value > 0xffffffffffffffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 56) & 0x7f)); - } - if (value > 0x1ffffffffffffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 49) & 0x7f)); - } - if (value > 0x3ffffffffffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 42) & 0x7f)); - } - if (value > 0x7ffffffffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 35) & 0x7f)); - } - if (value > 0xfffffffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 28) & 0x7f)); - } - if (value > 0x1fffffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 21) & 0x7f)); - } - if (value > 0x3fffL || value < 0L) { - this.write(0x80 | ((int) (value >>> 14) & 0x7f)); - } - if (value > 0x7fL || value < 0L) { - this.write(0x80 | ((int) (value >>> 7) & 0x7f)); - } - this.write((int) value & 0x7f); - - return this; - } - - public long readVLong() { - byte leading = this.read(); - if (leading == 0x80) { - E.checkArgument(false, - "Unexpected varlong with leading byte '0x%s'", - Bytes.toHex(leading)); - } - long value = leading & 0x7fL; - if (leading >= 0) { - assert (leading & 0x80) == 0; - return value; - } - - int i = 1; - for (; i < 10; i++) { - byte b = this.read(); - if (b >= 0) { - value = b | (value << 7); - break; - } else { - value = (b & 0x7f) | (value << 7); - } - } - - if (i >= 10) { - E.checkArgument(false, - "Unexpected varlong %s with too many bytes(%s)", - value, i + 1); - } - if (i >= 9 && (leading & 0x7e) != 0) { - E.checkArgument(false, - "Unexpected varlong %s with leading byte '0x%s'", - value, Bytes.toHex(leading)); - } - return value; - } - - public BytesBuffer writeProperty(PropertyKey pkey, Object value) { - if (pkey.cardinality() == Cardinality.SINGLE) { - this.writeProperty(pkey.dataType(), value); - return this; - } - - assert pkey.cardinality() == Cardinality.LIST || - pkey.cardinality() == Cardinality.SET; - Collection values = (Collection) value; - this.writeVInt(values.size()); - for (Object o : values) { - this.writeProperty(pkey.dataType(), o); - } - return this; - } - - public Object readProperty(PropertyKey pkey) { - if (pkey.cardinality() == Cardinality.SINGLE) { - return this.readProperty(pkey.dataType()); - } - - assert pkey.cardinality() == Cardinality.LIST || - pkey.cardinality() == Cardinality.SET; - int size = this.readVInt(); - Collection values = pkey.newValue(); - for (int i = 0; i < size; i++) { - values.add(this.readProperty(pkey.dataType())); - } - return values; - } - - public void writeProperty(DataType dataType, Object value) { - switch (dataType) { - case BOOLEAN: - this.writeVInt(((Boolean) value) ? 1 : 0); - break; - case BYTE: - this.writeVInt((Byte) value); - break; - case INT: - this.writeVInt((Integer) value); - break; - case FLOAT: - this.writeFloat((Float) value); - break; - case LONG: - this.writeVLong((Long) value); - break; - case DATE: - this.writeVLong(((Date) value).getTime()); - break; - case DOUBLE: - this.writeDouble((Double) value); - break; - case TEXT: - this.writeString((String) value); - break; - case BLOB: - byte[] bytes = value instanceof byte[] ? (byte[]) value : ((Blob) value).bytes(); - this.writeBigBytes(bytes); - break; - case UUID: - UUID uuid = (UUID) value; - // Generally writeVLong(uuid) can't save space - this.writeLong(uuid.getMostSignificantBits()); - this.writeLong(uuid.getLeastSignificantBits()); - break; - default: - // TODO: replace Kryo with Fury (https://github.com/apache/fury) - this.writeBytes(KryoUtil.toKryoWithType(value)); - break; - } - } - - public static byte getType(int value) { - return (byte) (value & 0x3f); - } - - public Object readProperty(DataType dataType) { - switch (dataType) { - case BOOLEAN: - return this.readVInt() == 1; - case BYTE: - return (byte) this.readVInt(); - case INT: - return this.readVInt(); - case FLOAT: - return this.readFloat(); - case LONG: - return this.readVLong(); - case DATE: - return new Date(this.readVLong()); - case DOUBLE: - return this.readDouble(); - case TEXT: - return this.readString(); - case BLOB: - return Blob.wrap(this.readBigBytes()); - case UUID: - return new UUID(this.readLong(), this.readLong()); - default: - // TODO: replace Kryo with Fury (https://github.com/apache/fury) - return KryoUtil.fromKryoWithType(this.readBytes()); - } - } - - public BytesBuffer writeId(Id id) { - switch (id.type()) { - case LONG: - // Number Id - long value = id.asLong(); - this.writeNumber(value); - break; - case UUID: - // UUID ID - byte[] bytes = id.asBytes(); - assert bytes.length == Id.UUID_LENGTH; - this.writeUInt8(0x7f); // 0b01111111 means UUID - this.write(bytes); - break; - case EDGE: - // Edge ID - this.writeUInt8(0x7e); // 0b01111110 means EdgeId - this.writeEdgeId(id); - break; - default: - // String Id (VertexID) - bytes = id.asBytes(); - int len = bytes.length; - if (len <= 0) { - E.checkArgument(false, "Can't write empty id"); - } - if (len > ID_LEN_MAX) { - E.checkArgument(false, "Big id max length is %s, but got %s {%s}", - ID_LEN_MAX, len, id); - } - len -= 1; // mapping [1, 16384] to [0, 16383] - if (len <= 0x3f) { - // If length is <= 63, use a single byte with the highest bit set to 1 - this.writeUInt8(len | 0x80); - } else { - int high = len >> 8; - int low = len & 0xff; - // Write high 8 bits with highest two bits set to 11 - this.writeUInt8(high | 0xc0); - this.writeUInt8(low); - } - this.write(bytes); - break; - } - return this; - } - - public Id readId() { - byte b = this.read(); - boolean number = (b & 0x80) == 0; - if (number) { - if (b == 0x7f) { - // UUID Id - return IdGenerator.of(this.read(Id.UUID_LENGTH), IdType.UUID); - } else if (b == 0x7e) { - // Edge Id - return this.readEdgeId(); - } else { - // Number Id - return IdGenerator.of(this.readNumber(b)); - } - } else { - // String Id - int len = b & 0x3f; // Take the lowest 6 bits as part of the length - if ((b & 0x40) != 0) { // If the 7th bit is set, length information spans 2 bytes - int high = len << 8; - int low = this.readUInt8(); - len = high + low; - } - len += 1; // restore [0, 16383] to [1, 16384] - byte[] id = this.read(len); - return IdGenerator.of(id, IdType.STRING); - } - } - - public BytesBuffer writeEdgeId(Id id) { - // owner-vertex + dir + edge-label + sub-edge-label + sort-values + other-vertex - EdgeId edge = (EdgeId) id; - this.writeId(edge.ownerVertexId()); - this.write(edge.directionCode()); - this.writeId(edge.edgeLabelId()); - this.writeId(edge.subLabelId()); - this.writeStringWithEnding(edge.sortValues()); - this.writeId(edge.otherVertexId()); - return this; - } - - public Id readEdgeId() { - return new EdgeId(this.readId(), EdgeId.directionFromCode(this.read()), - this.readId(), this.readId(), this.readStringWithEnding(), - this.readId()); - } - - public BytesBuffer writeIndexId(Id id, HugeType type) { - return this.writeIndexId(id, type, true); - } - - public BytesBuffer writeIndexId(Id id, HugeType type, boolean withEnding) { - byte[] bytes = id.asBytes(); - int len = bytes.length; - if (len == 0) { - E.checkArgument(false, "Can't write empty id"); - } - - this.write(bytes); - if (type.isStringIndex()) { - if (Bytes.contains(bytes, STRING_ENDING_BYTE)) { - // Not allow STRING_ENDING_BYTE to exist in string index id - E.checkArgument(false, - "The %s type index id can't contains " + - "byte '0x%s', but got: 0x%s", - type, Bytes.toHex(STRING_ENDING_BYTE), Bytes.toHex(bytes)); - } - if (withEnding) { - this.writeStringWithEnding(""); - } - } - return this; - } - - public BinaryId readIndexId(HugeType type) { - byte[] id; - if (type.isRange4Index()) { - // HugeTypeCode 1 byte + IndexLabel 4 bytes + fieldValue 4 bytes - id = this.read(9); - } else if (type.isRange8Index()) { - // HugeTypeCode 1 byte + IndexLabel 4 bytes + fieldValue 8 bytes - id = this.read(13); - } else { - assert type.isStringIndex(); - id = this.readBytesWithEnding(); - } - return new BinaryId(id, IdGenerator.of(id, IdType.STRING)); - } - - public BinaryId asId() { - return new BinaryId(this.bytes(), null); - } - - public BinaryId parseId(HugeType type, boolean enablePartition) { - if (type.isIndex()) { - return this.readIndexId(type); - } - // Parse id from bytes - if ((type.isVertex() || type.isEdge()) && enablePartition) { - this.readShort(); - } - int start = this.buffer.position(); - /* - * Since edge id in edges table doesn't prefix with leading 0x7e, - * so readId() will return the source vertex id instead of edge id, - * can't call: type.isEdge() ? this.readEdgeId() : this.readId(); - */ - Id id = this.readId(); - int end = this.buffer.position(); - int len = end - start; - byte[] bytes = new byte[len]; - System.arraycopy(this.array(), start, bytes, 0, len); - return new BinaryId(bytes, id); - } - - /** - * Analyze olap id - * @param type - * @param isOlap - * @return - */ - public BinaryId parseOlapId(HugeType type, boolean isOlap) { - if (type.isIndex()) { - return this.readIndexId(type); - } - // Parse id from bytes - int start = this.buffer.position(); - // OLAP {PropertyKey}{VertexId} - if (isOlap) { - // Read olap property id first - Id pkId = this.readId(); - } - Id id = this.readId(); - int end = this.buffer.position(); - int len = end - start; - byte[] bytes = new byte[len]; - System.arraycopy(this.array(), start, bytes, 0, len); - return new BinaryId(bytes, id); - } - - private void writeNumber(long val) { - /* - * 8 kinds of number, 2 ~ 9 bytes number: - * 0b 0kkksxxx X... - * 0(1 bit) + kind(3 bits) + signed(1 bit) + number(n bits) - * - * 2 byte : 0b 0000 1xxx X(8 bits) [0, 2047] - * 0b 0000 0xxx X(8 bits) [-2048, -1] - * 3 bytes: 0b 0001 1xxx X X [0, 524287] - * 0b 0001 0xxx X X [-524288, -1] - * 4 bytes: 0b 0010 1xxx X X X [0, 134217727] - * 0b 0010 0xxx X X X [-134217728, -1] - * 5 bytes: 0b 0011 1xxx X X X X [0, 2^35 - 1] - * 0b 0011 0xxx X X X X [-2^35, -1] - * 6 bytes: 0b 0100 1xxx X X X X X [0, 2^43 - 1] - * 0b 0100 0xxx X X X X X [-2^43, -1] - * 7 bytes: 0b 0101 1xxx X X X X X X [0, 2^51 - 1] - * 0b 0101 0xxx X X X X X X [-2^51, -1] - * 8 bytes: 0b 0110 1xxx X X X X X X X [0, 2^59 - 1] - * 0b 0110 0xxx X X X X X X X [-2^59, -1] - * 9 bytes: 0b 0111 1000 X X X X X X X X [0, 2^64 - 1] - * 0b 0111 0000 X X X X X X X X [-2^64, -1] - * - * NOTE: 0b 0111 1111 is used by 128 bits UUID - * 0b 0111 1110 is used by EdgeId - */ - int positive = val >= 0 ? 0x08 : 0x00; - if (~0x7ffL <= val && val <= 0x7ffL) { - int high3bits = (int) (val >> 8) & 0x07; - this.writeUInt8(0x00 | positive | high3bits); - this.writeUInt8((byte) val); - } else if (~0x7ffffL <= val && val <= 0x7ffffL) { - int high3bits = (int) (val >> 16) & 0x07; - this.writeUInt8(0x10 | positive | high3bits); - this.writeShort((short) val); - } else if (~0x7ffffffL <= val && val <= 0x7ffffffL) { - int high3bits = (int) (val >> 24 & 0x07); - this.writeUInt8(0x20 | positive | high3bits); - this.write((byte) (val >> 16)); - this.writeShort((short) val); - } else if (~0x7ffffffffL <= val && val <= 0x7ffffffffL) { - int high3bits = (int) (val >> 32) & 0x07; - this.writeUInt8(0x30 | positive | high3bits); - this.writeInt((int) val); - } else if (~0x7ffffffffffL <= val && val <= 0x7ffffffffffL) { - int high3bits = (int) (val >> 40) & 0x07; - this.writeUInt8(0x40 | positive | high3bits); - this.write((byte) (val >> 32)); - this.writeInt((int) val); - } else if (~0x7ffffffffffffL <= val && val <= 0x7ffffffffffffL) { - int high3bits = (int) (val >> 48) & 0x07; - this.writeUInt8(0x50 | positive | high3bits); - this.writeShort((short) (val >> 32)); - this.writeInt((int) val); - } else if (~0x7ffffffffffffffL <= val && val <= 0x7ffffffffffffffL) { - int high3bits = (int) (val >> 56) & 0x07; - this.writeUInt8(0x60 | positive | high3bits); - this.write((byte) (val >> 48)); - this.writeShort((short) (val >> 32)); - this.writeInt((int) val); - } else { - // high3bits is always 0b000 for 9 bytes number - this.writeUInt8(0x70 | positive); - this.writeLong(val); - } - } - - private long readNumber(byte b) { - if ((b & 0x80) != 0) { - E.checkArgument(false, - "Not a number type with prefix byte '0x%s'", - Bytes.toHex(b)); - } - // Parse the kind from byte 0kkksxxx - int kind = b >>> 4; - boolean positive = (b & 0x08) > 0; - long high3bits = b & 0x07; - long value = high3bits << ((kind + 1) * 8); - switch (kind) { - case 0: - value |= this.readUInt8(); - break; - case 1: - value |= this.readUInt16(); - break; - case 2: - value |= (long) this.readUInt8() << 16 | this.readUInt16(); - break; - case 3: - value |= this.readUInt32(); - break; - case 4: - value |= (long) this.readUInt8() << 32 | this.readUInt32(); - break; - case 5: - value |= (long) this.readUInt16() << 32 | this.readUInt32(); - break; - case 6: - value |= (long) this.readUInt8() << 48 | - (long) this.readUInt16() << 32 | - this.readUInt32(); - break; - case 7: - assert high3bits == 0L; - value |= this.readLong(); - break; - default: - throw new AssertionError("Invalid length of number: " + kind); - } - if (!positive && kind < 7) { - // Restore the bits of the original negative number - long mask = Long.MIN_VALUE >> (52 - kind * 8); - value |= mask; - } - return value; - } - - private byte[] readBytesWithEnding() { - int start = this.buffer.position(); - boolean foundEnding = false; - int remaining = this.remaining(); - for (int i = 0; i < remaining; i++) { - byte current = this.read(); - if (current == STRING_ENDING_BYTE) { - foundEnding = true; - break; - } - } - if (!foundEnding) { - E.checkArgument(false, - "Not found ending '0x%s'", - Bytes.toHex(STRING_ENDING_BYTE)); - } - int end = this.buffer.position() - 1; - int len = end - start; - if (len <= 0) { - return BYTES_EMPTY; - } - byte[] bytes = new byte[len]; - System.arraycopy(this.array(), start, bytes, 0, len); - return bytes; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/GraphSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/GraphSerializer.java index 2d14df1c84..548ddba7ad 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/GraphSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/GraphSerializer.java @@ -18,14 +18,14 @@ package org.apache.hugegraph.backend.serializer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.iterator.CIter; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.structure.HugeVertexProperty; import org.apache.hugegraph.type.HugeType; @@ -49,9 +49,9 @@ public interface GraphSerializer { CIter readEdges(HugeGraph graph, BackendEntry bytesEntry); - BackendEntry writeIndex(HugeIndex index); + BackendEntry writeIndex(Index index); - HugeIndex readIndex(HugeGraph graph, ConditionQuery query, BackendEntry entry); + Index readIndex(HugeGraph graph, ConditionQuery query, BackendEntry entry); BackendEntry writeId(HugeType type, Id id); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SchemaSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SchemaSerializer.java index 74e2dcc09f..aea85495b7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SchemaSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SchemaSerializer.java @@ -19,10 +19,10 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; public interface SchemaSerializer { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SerializerFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SerializerFactory.java index 213cf2b264..42962d5757 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SerializerFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/SerializerFactory.java @@ -20,7 +20,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.config.HugeConfig; public class SerializerFactory { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableBackendEntry.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableBackendEntry.java index 918a95b511..34d15e2b11 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableBackendEntry.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableBackendEntry.java @@ -27,7 +27,8 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang3.NotImplementedException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; @@ -252,17 +253,17 @@ public int columnsSize() { } @Override - public Collection columns() { + public Collection columns() { throw new NotImplementedException("Not supported by table backend"); } @Override - public void columns(Collection bytesColumns) { + public void columns(Collection bytesColumns) { throw new NotImplementedException("Not supported by table backend"); } @Override - public void columns(BackendEntry.BackendColumn bytesColumn) { + public void columns(BackendColumn bytesColumn) { throw new NotImplementedException("Not supported by table backend"); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializer.java index a2e3279976..e322e90d11 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializer.java @@ -23,26 +23,26 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.IdUtil; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdUtil; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.structure.HugeProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.structure.HugeVertexProperty; @@ -83,7 +83,7 @@ protected TableBackendEntry newBackendEntry(SchemaElement e) { return newBackendEntry(e.type(), e.id()); } - protected TableBackendEntry newBackendEntry(HugeIndex index) { + protected TableBackendEntry newBackendEntry(Index index) { return newBackendEntry(index.type(), index.id()); } @@ -305,7 +305,7 @@ public HugeEdge readEdge(HugeGraph graph, BackendEntry backendEntry) { } @Override - public BackendEntry writeIndex(HugeIndex index) { + public BackendEntry writeIndex(Index index) { TableBackendEntry entry = newBackendEntry(index); /* * When field-values is null and elementIds size is 0, it is @@ -327,7 +327,7 @@ public BackendEntry writeIndex(HugeIndex index) { } @Override - public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, + public Index readIndex(HugeGraph graph, ConditionQuery query, BackendEntry backendEntry) { E.checkNotNull(graph, "serializer graph"); if (backendEntry == null) { @@ -342,7 +342,7 @@ public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, Number expiredTime = entry.column(HugeKeys.EXPIRED_TIME); IndexLabel indexLabel = graph.indexLabel(this.toId(indexLabelId)); - HugeIndex index = new HugeIndex(graph, indexLabel); + Index index = new Index(graph, indexLabel); index.fieldValues(indexValues); long expired = index.hasTtl() ? expiredTime.longValue() : 0L; for (Object elemId : elemIds) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializerV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializerV2.java index 54f9e4cf54..b2ec49bde6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializerV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TableSerializerV2.java @@ -18,13 +18,13 @@ package org.apache.hugegraph.backend.serializer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextBackendEntry.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextBackendEntry.java index 2dfdb2cba9..f1878fde35 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextBackendEntry.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextBackendEntry.java @@ -27,8 +27,9 @@ import java.util.Set; import java.util.concurrent.ConcurrentSkipListMap; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java index 2d5cb81ec1..5a7ca40f7b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/TextSerializer.java @@ -24,32 +24,32 @@ import java.util.Map; import org.apache.commons.lang.NotImplementedException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.IdUtil; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdUtil; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.iterator.CIter; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; -import org.apache.hugegraph.structure.HugeIndex.IdWithExpiredTime; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.Index.IdWithExpiredTime; import org.apache.hugegraph.structure.HugeProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.structure.HugeVertexProperty; @@ -363,7 +363,7 @@ public CIter readEdges(HugeGraph graph, BackendEntry bytesEntry) { } @Override - public BackendEntry writeIndex(HugeIndex index) { + public BackendEntry writeIndex(Index index) { TextBackendEntry entry = newBackendEntry(index.type(), index.id()); if (index.fieldValues() == null && index.elementIds().isEmpty()) { /* @@ -386,7 +386,7 @@ public BackendEntry writeIndex(HugeIndex index) { } @Override - public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, + public Index readIndex(HugeGraph graph, ConditionQuery query, BackendEntry backendEntry) { E.checkNotNull(graph, "serializer graph"); if (backendEntry == null) { @@ -402,7 +402,7 @@ public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, formatSyspropName(HugeKeys.ELEMENT_IDS)); IndexLabel indexLabel = IndexLabel.label(graph, readId(indexLabelId)); - HugeIndex index = new HugeIndex(graph, indexLabel); + Index index = new Index(graph, indexLabel); index.fieldValues(JsonUtil.fromJson(indexValues, Object.class)); for (IdWithExpiredTime elemId : readElementIds(elemIds)) { long expiredTime = elemId.expiredTime(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java index adb3c8c400..89e9fd8ffc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java @@ -18,10 +18,10 @@ package org.apache.hugegraph.backend.store; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.exception.ConnectionException; import org.apache.hugegraph.iterator.ExtendableIterator; import org.apache.hugegraph.iterator.FlatMapperIterator; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStoreProvider.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStoreProvider.java index ff9ff00d4d..2ec8662375 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStoreProvider.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStoreProvider.java @@ -21,7 +21,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.raft.StoreSnapshotFile; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.config.HugeConfig; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntry.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntry.java index b1a5f89dc1..3e40668b76 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntry.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntry.java @@ -21,60 +21,16 @@ import java.util.Iterator; import java.util.NoSuchElementException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.WrappedIterator; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.Idfiable; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.StringEncoding; public interface BackendEntry extends Idfiable { - class BackendColumn implements Comparable { - - public byte[] name; - public byte[] value; - - public static BackendColumn of(byte[] name, byte[] value) { - BackendColumn col = new BackendColumn(); - col.name = name; - col.value = value; - return col; - } - - @Override - public String toString() { - return String.format("%s=%s", - StringEncoding.decode(name), - StringEncoding.decode(value)); - } - - @Override - public int compareTo(BackendColumn other) { - if (other == null) { - return 1; - } - return Bytes.compare(this.name, other.name); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof BackendColumn)) { - return false; - } - BackendColumn other = (BackendColumn) obj; - return Bytes.equals(this.name, other.name) && - Bytes.equals(this.value, other.value); - } - - public int hashCode() { - return this.name.hashCode() ^ - this.value.hashCode(); - } - - } - HugeType type(); @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntryIterator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntryIterator.java index 20469f77aa..e5d2acaa40 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntryIterator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendEntryIterator.java @@ -19,10 +19,10 @@ import java.util.NoSuchElementException; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.exception.LimitExceedException; import org.apache.hugegraph.exception.NotSupportException; import org.apache.hugegraph.iterator.CIter; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendMutation.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendMutation.java index 5b17fdf8e9..9d301ac700 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendMutation.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendMutation.java @@ -23,8 +23,8 @@ import java.util.Map; import java.util.Set; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.ExtendableIterator; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendProviderFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendProviderFactory.java index 2612ea3a07..c8e94d145f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendProviderFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendProviderFactory.java @@ -23,7 +23,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.memory.InMemoryDBStoreProvider; import org.apache.hugegraph.backend.store.raft.RaftBackendStoreProvider; import org.apache.hugegraph.config.CoreOptions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java index 6486d353c1..a1a28b285e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java @@ -22,9 +22,9 @@ import java.util.function.Function; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendTable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendTable.java index a9ee4b5c72..91b6ef7922 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendTable.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendTable.java @@ -24,9 +24,10 @@ import java.util.List; import org.apache.commons.lang3.NotImplementedException; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.backend.Shard; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/Shard.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/Shard.java deleted file mode 100644 index 3f1d2bf9e8..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/Shard.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.backend.store; - -/** - * Shard is used for distributed backend storage scanning. - * operations. Each shard represents a range of tokens for a node. - * Reading data from a given shard does not cross multiple nodes. - */ -public class Shard { - - // token range start - private String start; - // token range end - private String end; - // partitions count in this range - private long length; - - public Shard(String start, String end, long length) { - this.start = start; - this.end = end; - this.length = length; - } - - public String start() { - return this.start; - } - - public void start(String start) { - this.start = start; - } - - public String end() { - return this.end; - } - - public void end(String end) { - this.end = end; - } - - public long length() { - return this.length; - } - - public void length(long length) { - this.length = length; - } - - @Override - public String toString() { - return String.format("Shard{start=%s, end=%s, length=%s}", - this.start, this.end, this.length); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/SystemSchemaStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/SystemSchemaStore.java index 1ce7700ad0..d32cc3514c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/SystemSchemaStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/SystemSchemaStore.java @@ -19,8 +19,8 @@ import java.util.Map; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.type.define.CollectionType; import org.apache.hugegraph.util.collection.CollectionFactory; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBStore.java index c482749744..3368256482 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBStore.java @@ -22,10 +22,10 @@ import java.util.Iterator; import java.util.Map; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.LocalCounter; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.TextBackendEntry; import org.apache.hugegraph.backend.store.AbstractBackendStore; import org.apache.hugegraph.backend.store.BackendAction; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTable.java index 4768080905..ce8d5ec4f3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTable.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTable.java @@ -25,21 +25,21 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.serializer.TextBackendEntry; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendSession; import org.apache.hugegraph.backend.store.BackendTable; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.exception.NotSupportException; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTables.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTables.java index 445c28a5d6..8ce4a8e86f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTables.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/memory/InMemoryDBTables.java @@ -29,21 +29,21 @@ import java.util.SortedMap; import java.util.concurrent.ConcurrentSkipListMap; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.RangeConditions; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.RangeConditions; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.serializer.TextBackendEntry; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendSession; import org.apache.hugegraph.iterator.ExtendableIterator; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.E; @@ -429,7 +429,7 @@ public Iterator query(BackendSession session, } assert fieldValue != null && indexLabelId != null; - Id id = HugeIndex.formatIndexId(query.resultType(), + Id id = Index.formatIndexId(query.resultType(), indexLabelId, fieldValue); IdQuery q = new IdQuery(query, id); q.offset(query.offset()); @@ -502,7 +502,7 @@ public Iterator query(BackendSession session, RangeConditions range = new RangeConditions(relations); if (range.keyEq() != null) { - Id id = HugeIndex.formatIndexId(query.resultType(), + Id id = Index.formatIndexId(query.resultType(), indexLabelId, range.keyEq()); IdQuery q = new IdQuery(query, id); q.offset(query.offset()); @@ -529,7 +529,7 @@ private Iterator betweenQuery(Id indexLabelId, // Field value < keyMax keyMin = NumericUtil.minValueOf(keyMax.getClass()); } - Id min = HugeIndex.formatIndexId(type, indexLabelId, keyMin); + Id min = Index.formatIndexId(type, indexLabelId, keyMin); if (keyMax == null) { // Field value > keyMin @@ -537,7 +537,7 @@ private Iterator betweenQuery(Id indexLabelId, indexLabelId = IdGenerator.of(indexLabelId.asLong() + 1L); keyMax = NumericUtil.minValueOf(keyMin.getClass()); } - Id max = HugeIndex.formatIndexId(type, indexLabelId, keyMax); + Id max = Index.formatIndexId(type, indexLabelId, keyMax); max = keyMaxEq ? rs.floorKey(max) : rs.lowerKey(max); if (max == null) { @@ -569,9 +569,9 @@ public void delete(BackendSession session, TextBackendEntry entry) { return; } Id indexLabelId = IdGenerator.of(Long.parseLong(indexLabel)); - Id min = HugeIndex.formatIndexId(entry.type(), indexLabelId, 0L); + Id min = Index.formatIndexId(entry.type(), indexLabelId, 0L); indexLabelId = IdGenerator.of(indexLabelId.asLong() + 1L); - Id max = HugeIndex.formatIndexId(entry.type(), indexLabelId, 0L); + Id max = Index.formatIndexId(entry.type(), indexLabelId, 0L); SortedMap subStore; subStore = this.store().subMap(min, max); Iterator> iter; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStore.java index 1765562127..cbdd5c5bd1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStore.java @@ -23,8 +23,8 @@ import java.util.function.Function; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendFeatures; import org.apache.hugegraph.backend.store.BackendMutation; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStoreProvider.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStoreProvider.java index ecdff19bd5..ff6cfee8c6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStoreProvider.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftBackendStoreProvider.java @@ -21,7 +21,7 @@ import java.util.concurrent.Future; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.backend.store.BackendStoreProvider; import org.apache.hugegraph.backend.store.raft.rpc.RaftRequests.StoreAction; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftClosure.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftClosure.java index bd4e45da42..eb6be8cd0b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftClosure.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftClosure.java @@ -23,7 +23,7 @@ import java.util.concurrent.TimeoutException; import java.util.function.Supplier; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.util.Log; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftContext.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftContext.java index 3928a4127f..ea2e92bfc8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftContext.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftContext.java @@ -30,11 +30,11 @@ import java.util.concurrent.ThreadPoolExecutor; import org.apache.commons.io.FileUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.backend.cache.Cache; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendAction; import org.apache.hugegraph.backend.store.BackendMutation; import org.apache.hugegraph.backend.store.BackendStore; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftException.java index 85e6915bf8..4610d09a77 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftException.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftException.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.backend.store.raft; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public class RaftException extends HugeException { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftGroupManagerImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftGroupManagerImpl.java index 0f231d734c..c0a144030c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftGroupManagerImpl.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftGroupManagerImpl.java @@ -20,7 +20,7 @@ import java.util.List; import java.util.stream.Collectors; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.raft.rpc.RaftRequests.AddPeerRequest; import org.apache.hugegraph.backend.store.raft.rpc.RaftRequests.ListPeersRequest; import org.apache.hugegraph.backend.store.raft.rpc.RaftRequests.ListPeersResponse; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftNode.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftNode.java index a8e07b4114..3b39ea3de0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftNode.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/RaftNode.java @@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.util.LZ4Util; import org.apache.hugegraph.util.Log; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreCommand.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreCommand.java index f49f94348f..3f25aaf5e1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreCommand.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreCommand.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.backend.store.raft; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.raft.rpc.RaftRequests.StoreAction; import org.apache.hugegraph.backend.store.raft.rpc.RaftRequests.StoreType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreSerializer.java index 69937737da..c76afb9d64 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreSerializer.java @@ -21,13 +21,13 @@ import java.util.Iterator; import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendAction; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendMutation; import org.apache.hugegraph.backend.store.raft.RaftBackendStore.IncrCounter; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreStateMachine.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreStateMachine.java index df54a8276d..a6237ce8fb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreStateMachine.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/StoreStateMachine.java @@ -23,8 +23,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendMutation; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.backend.store.raft.RaftBackendStore.IncrCounter; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/rpc/RpcForwarder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/rpc/RpcForwarder.java index 0944f5cc39..ba4973d69d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/rpc/RpcForwarder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/raft/rpc/RpcForwarder.java @@ -19,7 +19,7 @@ import java.util.concurrent.ExecutionException; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.raft.RaftClosure; import org.apache.hugegraph.backend.store.raft.RaftContext; import org.apache.hugegraph.backend.store.raft.RaftStoreClosure; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntIntMap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntIntMap.java index 1b2a4293ea..02d3261590 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntIntMap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntIntMap.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.Arrays; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public final class IntIntMap implements RamMap { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntLongMap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntLongMap.java index bc980db5a5..ccf7db5a30 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntLongMap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntLongMap.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.Arrays; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public final class IntLongMap implements RamMap { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java index 0e2c58bddc..707f02c9be 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/RamTable.java @@ -35,18 +35,18 @@ import java.util.concurrent.ExecutorService; import org.apache.commons.io.FileUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.iterator.FlatMapperIterator; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/AbstractTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/AbstractTransaction.java index 43393252d2..0a5d527832 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/AbstractTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/AbstractTransaction.java @@ -20,14 +20,14 @@ import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.Transaction; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.serializer.AbstractSerializer; import org.apache.hugegraph.backend.store.BackendEntry; @@ -37,7 +37,7 @@ import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Action; import org.apache.hugegraph.type.define.CollectionType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java index 6faace9671..b333c929df 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java @@ -20,7 +20,6 @@ import java.nio.CharBuffer; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -31,12 +30,10 @@ import java.util.function.Function; import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.analyzer.Analyzer; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.IdHolder; import org.apache.hugegraph.backend.page.IdHolder.BatchIdHolder; import org.apache.hugegraph.backend.page.IdHolder.FixedIdHolder; @@ -46,14 +43,15 @@ import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.backend.page.PageState; import org.apache.hugegraph.backend.page.SortByCountIdHolderList; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.RangeConditions; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.Condition.RelationType; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.RangeConditions; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.Condition.RelationType; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.query.MatchedIndex; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.serializer.AbstractSerializer; import org.apache.hugegraph.backend.store.BackendEntry; @@ -67,15 +65,17 @@ import org.apache.hugegraph.job.EphemeralJob; import org.apache.hugegraph.job.system.DeleteExpiredJob; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; -import org.apache.hugegraph.structure.HugeIndex.IdWithExpiredTime; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.builder.IndexBuilder; +import org.apache.hugegraph.structure.Index.IdWithExpiredTime; import org.apache.hugegraph.structure.HugeProperty; +import org.apache.hugegraph.structure.BaseProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.task.EphemeralJobQueue; import org.apache.hugegraph.type.HugeType; @@ -97,18 +97,17 @@ public class GraphIndexTransaction extends AbstractTransaction { - public static final String START_SYMBOL = "("; - public static final String END_SYMBOL = ")"; - public static final String WORD_DELIMITER = "|"; + public static final String START_SYMBOL = IndexBuilder.START_SYMBOL; + public static final String END_SYMBOL = IndexBuilder.END_SYMBOL; + public static final String WORD_DELIMITER = IndexBuilder.WORD_DELIMITER; - private final Analyzer textAnalyzer; + private final IndexBuilder indexBuilder; private final int indexIntersectThresh; public GraphIndexTransaction(HugeGraphParams graph, BackendStore store) { super(graph, store); - this.textAnalyzer = graph.analyzer(); - assert this.textAnalyzer != null; + this.indexBuilder = new IndexBuilder(this.graph(), graph.analyzer()); final HugeConfig conf = graph.configuration(); this.indexIntersectThresh = @@ -137,27 +136,8 @@ public void updateLabelIndex(HugeElement element, boolean removed) { return; } - // Update label index if backend store not supports label-query - HugeIndex index = new HugeIndex(this.graph(), - IndexLabel.label(element.type())); - index.fieldValues(element.schemaLabel().id()); - index.elementIds(element.id(), element.expiredTime()); - - if (removed) { - this.doEliminate(this.serializer.writeIndex(index)); - } else { - this.doAppend(this.serializer.writeIndex(index)); - } - - if (element instanceof HugeEdge && ((EdgeLabel) label).hasFather()) { - HugeIndex fatherIndex = new HugeIndex(this.graph(), IndexLabel.label(element.type())); - fatherIndex.fieldValues(((EdgeLabel) label).fatherId()); - fatherIndex.elementIds(element.id(), element.expiredTime()); - if (removed) { - this.doEliminate(this.serializer.writeIndex(fatherIndex)); - } else { - this.doAppend(this.serializer.writeIndex(fatherIndex)); - } + for (Index index : this.indexBuilder.buildLabelIndex(element.element())) { + this.writeIndex(index, removed); } } @@ -168,39 +148,20 @@ public void updateVertexIndex(HugeVertex vertex, boolean removed) { return; } // Update index(only property, no edge) of a vertex - for (Id id : vertex.schemaLabel().indexLabels()) { - this.updateIndex(id, vertex, removed); - } + IndexBuilder.forEachIndexLabelId(vertex.element(), this.graph()::edgeLabel, + id -> this.updateIndex(id, vertex, removed)); } @Watched(prefix = "index") public void updateEdgeIndex(HugeEdge edge, boolean removed) { - // Update index of an edge - for (Id id : edge.schemaLabel().indexLabels()) { - this.updateIndex(id, edge, removed); - } - - EdgeLabel label = edge.schemaLabel(); - if (label.hasFather()) { - for (Id id : graph().edgeLabel(label.fatherId()).indexLabels()) { - this.updateIndex(id, edge, removed); - } - } + IndexBuilder.forEachIndexLabelId(edge.element(), this.graph()::edgeLabel, + id -> this.updateIndex(id, edge, removed)); } private void updateVertexOlapIndex(HugeVertex vertex, boolean removed) { - Set propKeys = vertex.getPropertyKeys(); - E.checkArgument(propKeys.size() == 1, - "Expect only 1 property for olap vertex, but got %s", - propKeys.size()); - Id pkId = propKeys.iterator().next(); - List indexLabels = this.params().schemaTransaction() - .getIndexLabels(); - for (IndexLabel il : indexLabels) { - if (il.indexFields().contains(pkId)) { - this.updateIndex(il.id(), vertex, removed); - } - } + IndexBuilder.forEachOlapIndexLabelId(vertex.element(), + () -> this.params().schemaTransaction().getIndexLabels().iterator(), + id -> this.updateIndex(id, vertex, removed)); } /** @@ -216,110 +177,18 @@ protected void updateIndex(Id ilId, HugeElement element, boolean removed) { E.checkArgument(indexLabel != null, "Not exist index label with id '%s'", ilId); - // Collect property values of index fields - List allPropValues = new ArrayList<>(); - int fieldsNum = indexLabel.indexFields().size(); - int firstNullField = fieldsNum; - for (Id fieldId : indexLabel.indexFields()) { - HugeProperty property = element.getProperty(fieldId); - if (property == null) { - E.checkState(hasNullableProp(element, fieldId), - "Non-null property '%s' is null for '%s'", - this.graph().propertyKey(fieldId), element); - if (firstNullField == fieldsNum) { - firstNullField = allPropValues.size(); - } - allPropValues.add(ConditionQuery.INDEX_VALUE_NULL); - } else { - allPropValues.add(property.value()); + this.indexBuilder.forEachIndex(element.element(), indexLabel, index -> { + Object value = index.fieldValues(); + if (indexLabel.indexType().isUnique() && !removed && + this.existUniqueValue(indexLabel, value, element.id())) { + throw new IllegalArgumentException(String.format( + "Unique constraint %s conflict is found for %s", indexLabel, element)); } - } - - if (firstNullField == 0 && !indexLabel.indexType().isUnique()) { - // The property value of first index field is null - return; - } - // Not build index for record with nullable field (except unique index) - List nnPropValues = allPropValues.subList(0, firstNullField); - - // Expired time - long expiredTime = element.expiredTime(); - - // Update index for each index type - switch (indexLabel.indexType()) { - case RANGE_INT: - case RANGE_FLOAT: - case RANGE_LONG: - case RANGE_DOUBLE: - E.checkState(nnPropValues.size() == 1, - "Expect only one property in range index"); - Object value = NumericUtil.convertToNumber(nnPropValues.get(0)); - this.updateIndex(indexLabel, value, element.id(), - expiredTime, removed); - break; - case SEARCH: - E.checkState(nnPropValues.size() == 1, - "Expect only one property in search index"); - value = nnPropValues.get(0); - Set words = - this.segmentWords(propertyValueToString(value)); - for (String word : words) { - this.updateIndex(indexLabel, word, element.id(), - expiredTime, removed); - } - break; - case SECONDARY: - // Secondary index maybe include multi prefix index - if (isCollectionIndex(nnPropValues)) { - /* - * Property value is a collection - * we should create index for each item - */ - for (Object propValue : (Collection) nnPropValues.get(0)) { - value = ConditionQuery.concatValues(propValue); - this.updateIndex(indexLabel, value, element.id(), - expiredTime, removed); - } - } else { - for (int i = 0, n = nnPropValues.size(); i < n; i++) { - List prefixValues = - nnPropValues.subList(0, i + 1); - value = ConditionQuery.concatValues(prefixValues); - this.updateIndex(indexLabel, value, element.id(), - expiredTime, removed); - } - } - break; - case SHARD: - value = ConditionQuery.concatValues(nnPropValues); - this.updateIndex(indexLabel, value, element.id(), - expiredTime, removed); - break; - case UNIQUE: - value = ConditionQuery.concatValues(allPropValues); - assert !"".equals(value); - Id id = element.id(); - // TODO: add lock for updating unique index - if (!removed && this.existUniqueValue(indexLabel, value, id)) { - throw new IllegalArgumentException(String.format( - "Unique constraint %s conflict is found for %s", - indexLabel, element)); - } - this.updateIndex(indexLabel, value, element.id(), - expiredTime, removed); - break; - default: - throw new AssertionError(String.format( - "Unknown index type '%s'", indexLabel.indexType())); - } + this.writeIndex(index, removed); + }); } - private void updateIndex(IndexLabel indexLabel, Object propValue, - Id elementId, long expiredTime, boolean removed) { - HugeIndex index = new HugeIndex(this.graph(), indexLabel); - index.fieldValues(propValue); - index.elementIds(elementId, expiredTime); - + private void writeIndex(Index index, boolean removed) { if (removed) { this.doEliminate(this.serializer.writeIndex(index)); } else { @@ -335,7 +204,7 @@ private boolean existUniqueValue(IndexLabel indexLabel, private boolean hasEliminateInTx(IndexLabel indexLabel, Object value, Id elementId) { - HugeIndex index = new HugeIndex(this.graph(), indexLabel); + Index index = new Index(this.graph(), indexLabel); index.fieldValues(value); index.elementIds(elementId); BackendEntry entry = this.serializer.writeIndex(index); @@ -351,7 +220,7 @@ private boolean existUniqueValueInStore(IndexLabel indexLabel, Object value) { try { exist = iterator.hasNext(); if (exist) { - HugeIndex index = this.serializer.readIndex(graph(), query, + Index index = this.serializer.readIndex(graph(), query, iterator.next()); this.removeExpiredIndexIfNeeded(index, query.showExpired()); // Memory backend might return empty BackendEntry @@ -507,7 +376,7 @@ private IdHolderList queryByUserprop(ConditionQuery query) { holders.addAll(this.doSearchIndex(query, index)); } else { // Do secondary-index, range-index or shard-index query - IndexQueries queries = index.constructIndexQueries(query); + IndexQueries queries = constructIndexQueries(query, index); assert !paging || queries.size() <= 1; IdHolder holder = this.doSingleOrJointIndex(queries); holders.add(holder); @@ -537,7 +406,7 @@ private IdHolderList doSearchIndex(ConditionQuery query, // Increase limit for union operation increaseLimit(q); } - IndexQueries queries = index.constructIndexQueries(q); + IndexQueries queries = constructIndexQueries(q, index); assert !query.paging() || queries.size() <= 1; IdHolder holder = this.doSingleOrJointIndex(queries); // NOTE: ids will be merged into one IdHolder if not in paging @@ -694,7 +563,7 @@ private IdHolder doIndexQueryBatch(IndexLabel indexLabel, Set ids = InsertionOrderUtil.newSet(); while ((batch == Query.NO_LIMIT || ids.size() < batch) && entries.hasNext()) { - HugeIndex index = this.serializer.readIndex(graph(), query, + Index index = this.serializer.readIndex(graph(), query, entries.next()); this.removeExpiredIndexIfNeeded(index, query.showExpired()); ids.addAll(index.elementIds()); @@ -708,7 +577,7 @@ private IdHolder doIndexQueryBatch(IndexLabel indexLabel, }, this.keepBackendIndexOrder(indexLabel, query)); } - private void recordIndexValue(ConditionQuery query, HugeIndex index) { + private void recordIndexValue(ConditionQuery query, Index index) { if (!shouldRecordIndexValue(query, index)) { return; } @@ -736,7 +605,7 @@ private PageIds doIndexQueryOnce(IndexLabel indexLabel, Set ids = InsertionOrderUtil.newSet(); entries = super.query(query).iterator(); while (entries.hasNext()) { - HugeIndex index = this.serializer.readIndex(graph(), query, + Index index = this.serializer.readIndex(graph(), query, entries.next()); this.removeExpiredIndexIfNeeded(index, query.showExpired()); ids.addAll(index.elementIds()); @@ -882,8 +751,8 @@ private ConditionQuery constructSearchQuery(ConditionQuery query, MatchedIndex i if (key instanceof Id && indexFields.contains(key)) { // This is an index field of search index Id field = (Id) key; - HugeProperty property = element.getProperty(field); - String propValue = propertyValueToString(property.value()); + BaseProperty property = element.getProperty(field); + String propValue = IndexBuilder.propertyValueToString(property.value()); String fieldValue = (String) query.userpropValue(field); if (this.matchSearchIndexWords(propValue, fieldValue)) { continue; @@ -907,46 +776,20 @@ private boolean matchSearchIndexWords(String propValue, String fieldValue) { } private Set segmentWords(String text) { - /* - Support 3 kinds of query: - - Text.contains("(word)"): query by user-specified word; - - Text.contains("(word1|word2|word3)"): query by user-specified words; - - Text.contains("words"): query by words splitted from analyzer; - Note: all kinds support words exact match - */ - if (text.startsWith(START_SYMBOL) && text.endsWith(END_SYMBOL)) { - String subText = text.substring(1, text.length() - 1); - if (subText.contains(WORD_DELIMITER)) { - String[] texts = StringUtils.split(subText, WORD_DELIMITER); - return ImmutableSet.copyOf(texts); - } else { - return ImmutableSet.of(subText); - } - } - Set segments = this.textAnalyzer.segment(text); - - /* - * Add original text to segments at the insertion stage, - * in order to can match fully words at the query stage. - */ - segments.add(text); - - // Ignore unicode \u0000 to \u0003 - segments.removeAll(ConditionQuery.IGNORE_SYM_SET); - return segments; + return this.indexBuilder.segmentWords(text); } private boolean needIndexForLabel() { return !this.store().features().supportsQueryByLabel(); } - private void removeExpiredIndexIfNeeded(HugeIndex index, + private void removeExpiredIndexIfNeeded(Index index, boolean showExpired) { if (this.store().features().supportsTtl() || showExpired) { return; } for (IdWithExpiredTime id : index.expiredElementIds()) { - HugeIndex removeIndex = index.clone(); + Index removeIndex = index.clone(); removeIndex.resetElementIds(); removeIndex.elementIds(id.id(), id.expiredTime()); DeleteExpiredJob.asyncDeleteExpiredObject(this.graph(), @@ -1183,7 +1026,7 @@ private static boolean cmn(List all, int m, int n, } private static boolean shouldRecordIndexValue(ConditionQuery query, - HugeIndex index) { + Index index) { // Currently, only range index has problems return query.originQuery() instanceof ConditionQuery && index.indexLabel().indexType().isRange(); @@ -1506,20 +1349,6 @@ private static Object toCollectionIfNeeded(PropertyKey pk, Object value) { return value; } - private static boolean isCollectionIndex(List propValues) { - return propValues.size() == 1 && - propValues.get(0) instanceof Collection; - } - - private static String propertyValueToString(Object value) { - /* - * Join collection items with white space if the value is Collection, - * or else keep the origin value. - */ - return value instanceof Collection ? - StringUtils.join(((Iterable) value), " ") : value.toString(); - } - private static NoIndexException noIndexException(HugeGraph graph, ConditionQuery query, Id label) { @@ -1557,10 +1386,6 @@ private static void validateIndexLabel(IndexLabel indexLabel) { indexLabel, indexLabel.status()); } - private static boolean hasNullableProp(HugeElement element, Id key) { - return element.schemaLabel().nullableKeys().contains(key); - } - private static Set relatedIndexLabels(HugeElement element) { Set indexLabels = InsertionOrderUtil.newSet(); Set indexLabelIds = element.schemaLabel().indexLabels(); @@ -1586,72 +1411,20 @@ private static void increaseLimit(Query query) { } protected void removeIndex(IndexLabel indexLabel) { - HugeIndex index = new HugeIndex(this.graph(), indexLabel); + Index index = new Index(this.graph(), indexLabel); this.doRemove(this.serializer.writeIndex(index)); } - private static class MatchedIndex { - - private final SchemaLabel schemaLabel; - private final Set indexLabels; - - public MatchedIndex(SchemaLabel schemaLabel, - Set indexLabels) { - this.schemaLabel = schemaLabel; - this.indexLabels = indexLabels; - } - - @SuppressWarnings("unused") - public SchemaLabel schemaLabel() { - return this.schemaLabel; - } - - public Set indexLabels() { - return Collections.unmodifiableSet(this.indexLabels); - } - - public IndexQueries constructIndexQueries(ConditionQuery query) { - // Condition query => Index Queries - if (this.indexLabels().size() == 1) { - /* - * Query by single index or composite index - */ - IndexLabel il = this.indexLabels().iterator().next(); - ConditionQuery indexQuery = constructQuery(query, il); - assert indexQuery != null; - return IndexQueries.of(il, indexQuery); - } else { - /* - * Query by joint indexes - */ - IndexQueries queries = buildJointIndexesQueries(query, this); - assert !queries.isEmpty(); - return queries; - } - } - - public boolean containsSearchIndex() { - for (IndexLabel il : this.indexLabels) { - if (il.indexType().isSearch()) { - return true; - } - } - return false; - } - - @Override - public int hashCode() { - return this.indexLabels.hashCode(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof MatchedIndex)) { - return false; - } - Set indexLabels = ((MatchedIndex) other).indexLabels; - return Objects.equals(this.indexLabels, indexLabels); + private static IndexQueries constructIndexQueries(ConditionQuery query, MatchedIndex index) { + if (index.indexLabels().size() == 1) { + IndexLabel label = index.indexLabels().iterator().next(); + ConditionQuery indexQuery = constructQuery(query, label); + assert indexQuery != null; + return IndexQueries.of(label, indexQuery); } + IndexQueries queries = buildJointIndexesQueries(query, index); + assert !queries.isEmpty(); + return queries; } private static class IndexQueries @@ -1832,7 +1605,7 @@ private long processRangeIndexLeft(ConditionQuery query, AbstractSerializer serializer = this.tx.serializer; for (Object value : indexValues) { - HugeIndex index = new HugeIndex(this.graph(), indexLabel); + Index index = new Index(this.graph(), indexLabel); index.elementIds(element.id()); index.fieldValues(value); this.tx.doEliminate(serializer.writeIndex(index)); @@ -1947,7 +1720,7 @@ private boolean deletedByError(ConditionQuery query, if (elem == null) { return false; } - return query.test(elem); + return query.test(elem.element()); } private boolean deletedByError(HugeElement element, diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java index 77ea7784ea..af48b7954e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java @@ -33,24 +33,24 @@ import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.SplicingIdGenerator; import org.apache.hugegraph.backend.page.IdHolderList; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.backend.page.QueryList; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryBatch; import org.apache.hugegraph.backend.query.QueryResultContext; import org.apache.hugegraph.backend.query.QueryResults; @@ -69,17 +69,17 @@ import org.apache.hugegraph.iterator.MapperIterator; import org.apache.hugegraph.job.system.DeleteExpiredJob; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.structure.HugeFeatures.HugeVertexFeatures; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.structure.HugeProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.structure.HugeVertexProperty; @@ -547,7 +547,7 @@ public QueryResults query(Query query) { public Number queryNumber(Query query) { boolean isConditionQuery = query instanceof ConditionQuery; boolean hasUpdate = this.hasUpdate(); - Aggregate aggregate = query.aggregateNotNull(); + Aggregate aggregate = query.aggregateNotNull(); if (hasUpdate && (query.resultType() == HugeType.VERTEX || query.resultType() == HugeType.EDGE)) { @@ -1951,7 +1951,7 @@ private boolean rightResultFromIndexQuery(QueryResultContext context, HugeElemen } } - if (!context.conditionFilterRequired() || cq.test(elem, context.resultsFilter())) { + if (!context.conditionFilterRequired() || cq.test(elem.element(), context.resultsFilter())) { if (cq.existLeftIndex(elem.id())) { /* * Both have correct and left index, wo should return true @@ -2031,7 +2031,7 @@ private Iterator joinTxVertices(Query query, return null; } // Filter vertices matched conditions - return q.test(v) ? v : null; + return q.test(v.element()) ? v : null; }; vertices = this.joinTxRecords(query, vertices, matchTxFunc, this.addedVertices, this.removedVertices, @@ -2049,7 +2049,7 @@ private Iterator joinTxEdges(Query query, Iterator edges, return null; } // Filter edges matched conditions - return q.test(e) ? e : q.test(e = e.switchOwner()) ? e : null; + return q.test(e.element()) ? e : q.test((e = e.switchOwner()).element()) ? e : null; }; edges = this.joinTxRecords(query, edges, matchTxFunc, this.addedEdges, this.removedEdges, @@ -2214,7 +2214,7 @@ public void updateIndex(Id ilId, HugeElement element, boolean removed) { this.indexTx.updateIndex(ilId, element, removed); } - public void removeIndex(HugeIndex index) { + public void removeIndex(Index index) { // TODO: use event to replace direct call this.checkOwnerThread(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/ISchemaTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/ISchemaTransaction.java index dce1276ced..f7eb879152 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/ISchemaTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/ISchemaTransaction.java @@ -20,13 +20,13 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.GraphMode; import org.apache.hugegraph.type.define.SchemaStatus; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IdCounter.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IdCounter.java index 87a10ce2c8..9d1ee4c845 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IdCounter.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IdCounter.java @@ -17,16 +17,16 @@ package org.apache.hugegraph.backend.tx; +import java.util.AbstractMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.pd.client.PDClient; import org.apache.hugegraph.pd.grpc.Pdpb; -import org.apache.hugegraph.store.term.HgPair; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; @@ -35,7 +35,7 @@ public class IdCounter { private static final int TIMES = 10000; private static final int DELTA = 10000; private static final String DELIMITER = "/"; - private static final Map> ids = + private static final Map> ids = new ConcurrentHashMap<>(); private final PDClient pdClient; private final String graphName; @@ -68,7 +68,7 @@ public long getCounter(HugeType type) { public synchronized void increaseCounter(HugeType type, long lowest) { String key = toKey(this.graphName, type); getCounterFromPd(type); - HgPair idPair = ids.get(key); + Map.Entry idPair = ids.get(key); AtomicLong currentId = idPair.getKey(); AtomicLong maxId = idPair.getValue(); if (currentId.longValue() >= lowest) { @@ -97,7 +97,7 @@ protected String toKey(String graphName, HugeType type) { public long getCounterFromPd(HugeType type) { AtomicLong currentId; AtomicLong maxId; - HgPair idPair; + Map.Entry idPair; String key = toKey(this.graphName, type); if ((idPair = ids.get(key)) == null) { synchronized (ids) { @@ -105,7 +105,7 @@ public long getCounterFromPd(HugeType type) { try { currentId = new AtomicLong(0); maxId = new AtomicLong(0); - idPair = new HgPair<>(currentId, maxId); + idPair = new AbstractMap.SimpleImmutableEntry<>(currentId, maxId); ids.put(key, idPair); } catch (Exception e) { throw new BackendException(String.format( diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IndexableTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IndexableTransaction.java index 7c481b05c2..8a3963989e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IndexableTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/IndexableTransaction.java @@ -18,7 +18,7 @@ package org.apache.hugegraph.backend.tx; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.BackendMutation; import org.apache.hugegraph.backend.store.BackendStore; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaIndexTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaIndexTransaction.java index 1fbade3190..c6122537bf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaIndexTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaIndexTransaction.java @@ -20,16 +20,16 @@ import java.util.Iterator; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.E; @@ -49,7 +49,7 @@ public void updateNameIndex(SchemaElement element, boolean removed) { IndexLabel indexLabel = IndexLabel.label(element.type()); // Update name index if backend store not supports name-query - HugeIndex index = new HugeIndex(this.graph(), indexLabel); + Index index = new Index(this.graph(), indexLabel); index.fieldValues(element.name()); index.elementIds(element.id()); @@ -96,7 +96,7 @@ private QueryResults queryByName(ConditionQuery query) { Iterator entries = super.query(indexQuery).iterator(); try { while (entries.hasNext()) { - HugeIndex index = this.serializer.readIndex(graph(), indexQuery, + Index index = this.serializer.readIndex(graph(), indexQuery, entries.next()); idQuery.query(index.elementIds()); Query.checkForceCapacity(idQuery.idsSize()); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransaction.java index f09c45cf71..af6e3dedc5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransaction.java @@ -25,12 +25,12 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.LocalCounter; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendStore; @@ -47,13 +47,13 @@ import org.apache.hugegraph.job.schema.SchemaJob; import org.apache.hugegraph.job.schema.VertexLabelRemoveJob; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.GraphMode; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java index 5eed063dae..5fcc35b46f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java @@ -23,8 +23,8 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.job.JobBuilder; @@ -41,13 +41,13 @@ import org.apache.hugegraph.meta.PdMetaDriver; import org.apache.hugegraph.meta.managers.SchemaMetaManager; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.GraphMode; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java index bbd634eb73..2f4e0d2cad 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java @@ -17,13 +17,13 @@ package org.apache.hugegraph.config; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.type.define.CollectionType; import org.apache.hugegraph.util.Bytes; -import static org.apache.hugegraph.backend.query.Query.COMMIT_BATCH; +import static org.apache.hugegraph.query.Query.COMMIT_BATCH; import static org.apache.hugegraph.config.OptionChecker.*; public class CoreOptions extends OptionHolder { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ConnectionException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ConnectionException.java index e6dc311815..70ac1bd1b7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ConnectionException.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ConnectionException.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.exception; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public class ConnectionException extends HugeException { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java deleted file mode 100644 index a5777f9fd1..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2017 HugeGraph Authors - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.exception; - -public interface ErrorCodeProvider { - - String format(Object... args); - - String with(String message); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ExistedException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ExistedException.java index b121588f0f..f6f64edf5d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ExistedException.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/ExistedException.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.exception; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.type.HugeType; public class ExistedException extends HugeException { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NoIndexException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NoIndexException.java index 3c1c788aee..2f72997972 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NoIndexException.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NoIndexException.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.exception; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public class NoIndexException extends HugeException { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotAllowException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotAllowException.java deleted file mode 100644 index 24bb495d7a..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotAllowException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.exception; - -import org.apache.hugegraph.HugeException; - -public class NotAllowException extends HugeException { - - private static final long serialVersionUID = -1407924451828873200L; - - public NotAllowException(String message) { - super(message); - } - - public NotAllowException(String message, Object... args) { - super(message, args); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotSupportException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotSupportException.java deleted file mode 100644 index 50148f6b00..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotSupportException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.exception; - -import org.apache.hugegraph.HugeException; - -public class NotSupportException extends HugeException { - - private static final long serialVersionUID = -2914329541122906234L; - private static final String PREFIX = "Not support "; - - public NotSupportException(String message) { - super(PREFIX + message); - } - - public NotSupportException(String message, Object... args) { - super(PREFIX + message, args); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java index db8d874e8e..208c96d4e8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java @@ -22,11 +22,11 @@ import com.google.common.collect.ImmutableList; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.EdgeLabelType; import org.apache.hugegraph.type.define.HugeKeys; @@ -34,7 +34,7 @@ public class GraphSONSchemaSerializer { public Map writeVertexLabel(VertexLabel vertexLabel) { - HugeGraph graph = vertexLabel.graph(); + HugeGraphSupplier graph = vertexLabel.graph(); assert graph != null; Map map = new LinkedHashMap<>(); @@ -61,7 +61,7 @@ public Map writeVertexLabel(VertexLabel vertexLabel) { } public Map writeEdgeLabel(EdgeLabel edgeLabel) { - HugeGraph graph = edgeLabel.graph(); + HugeGraphSupplier graph = edgeLabel.graph(); assert graph != null; Map map = new LinkedHashMap<>(); @@ -110,7 +110,7 @@ public Map writeEdgeLabel(EdgeLabel edgeLabel) { } public Map writePropertyKey(PropertyKey propertyKey) { - HugeGraph graph = propertyKey.graph(); + HugeGraphSupplier graph = propertyKey.graph(); assert graph != null; Map map = new LinkedHashMap<>(); @@ -128,7 +128,7 @@ public Map writePropertyKey(PropertyKey propertyKey) { } public Map writeIndexLabel(IndexLabel indexLabel) { - HugeGraph graph = indexLabel.graph(); + HugeGraphSupplier graph = indexLabel.graph(); assert graph != null; Map map = new LinkedHashMap<>(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphSONModule.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphSONModule.java index c7758989fe..158efdb2c4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphSONModule.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphSONModule.java @@ -33,18 +33,18 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.IdGenerator.LongId; -import org.apache.hugegraph.backend.id.IdGenerator.StringId; -import org.apache.hugegraph.backend.id.IdGenerator.UuidId; -import org.apache.hugegraph.backend.store.Shard; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator.LongId; +import org.apache.hugegraph.id.IdGenerator.StringId; +import org.apache.hugegraph.id.IdGenerator.UuidId; +import org.apache.hugegraph.backend.Shard; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.space.GraphSpace; import org.apache.hugegraph.space.Service; import org.apache.hugegraph.structure.HugeEdge; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphTypeSerializerRegistryBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphTypeSerializerRegistryBuilder.java index 28cb79bd74..d86eac92a6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphTypeSerializerRegistryBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGraphTypeSerializerRegistryBuilder.java @@ -28,14 +28,14 @@ import java.util.Optional; import java.util.function.Function; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.store.Shard; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.backend.Shard; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.Blob; import org.apache.tinkerpop.gremlin.structure.io.Buffer; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGryoModule.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGryoModule.java index 0feee228f6..cc1cbe6040 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGryoModule.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/HugeGryoModule.java @@ -21,14 +21,14 @@ import java.util.Map; import java.util.Optional; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.Id.IdType; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.StringEncoding; import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoIo; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/EphemeralJobBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/EphemeralJobBuilder.java index a8a0966fa7..785a2563ea 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/EphemeralJobBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/EphemeralJobBuilder.java @@ -18,8 +18,8 @@ package org.apache.hugegraph.job; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.task.TaskScheduler; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/GremlinJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/GremlinJob.java index 8bde61feb4..01c03d18ed 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/GremlinJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/GremlinJob.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.exception.LimitExceedException; import org.apache.hugegraph.traversal.optimize.HugeScriptTraversal; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/JobBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/JobBuilder.java index fc7067b419..0ee870030f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/JobBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/JobBuilder.java @@ -20,7 +20,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.task.TaskCallable; import org.apache.hugegraph.task.TaskScheduler; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/AbstractAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/AbstractAlgorithm.java index b30d3ac83a..ce72882d03 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/AbstractAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/AbstractAlgorithm.java @@ -29,10 +29,10 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.mutable.MutableLong; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.iterator.FilterIterator; import org.apache.hugegraph.iterator.FlatMapperIterator; import org.apache.hugegraph.job.UserJob; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/BfsTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/BfsTraverser.java index 4a6cda246e..ba73e2bd29 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/BfsTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/BfsTraverser.java @@ -23,7 +23,7 @@ import java.util.Map; import java.util.Stack; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/Consumers.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/Consumers.java index dc04bdf605..81680dbfa6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/Consumers.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/Consumers.java @@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.task.TaskManager.ContextCallable; import org.apache.hugegraph.util.ExecutorUtil; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/SubgraphStatAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/SubgraphStatAlgorithm.java index d6a1be8aa2..6646fae82d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/SubgraphStatAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/SubgraphStatAlgorithm.java @@ -23,7 +23,7 @@ import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.job.UserJob; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/AbstractCentAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/AbstractCentAlgorithm.java index 8ab6ca81f7..d34c245639 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/AbstractCentAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/AbstractCentAlgorithm.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.job.algorithm.cent; +import org.apache.hugegraph.util.TinkerPopUtil; + import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -24,7 +26,7 @@ import java.util.Map; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.MapperIterator; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.AbstractAlgorithm; @@ -114,7 +116,7 @@ protected GraphTraversal constructPathUnit( if (dir == null) { dir = Directions.BOTH; } - Direction direction = dir.direction(); + Direction direction = TinkerPopUtil.direction(dir); String[] labels = {}; if (label != null) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithm.java index 512d14a158..a3e267a146 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithm.java @@ -23,8 +23,8 @@ import java.util.Map; import org.apache.commons.lang3.mutable.MutableFloat; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.SplicingIdGenerator; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithmV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithmV2.java index ca99fddf8d..0bace3503b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithmV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/BetweennessCentralityAlgorithmV2.java @@ -22,8 +22,8 @@ import java.util.Map; import org.apache.commons.lang3.mutable.MutableFloat; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.BfsTraverser; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/ClosenessCentralityAlgorithmV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/ClosenessCentralityAlgorithmV2.java index 1519a2a456..ce92864ff5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/ClosenessCentralityAlgorithmV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/ClosenessCentralityAlgorithmV2.java @@ -20,8 +20,8 @@ import java.util.Iterator; import java.util.Map; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.exception.NotSupportException; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.BfsTraverser; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/DegreeCentralityAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/DegreeCentralityAlgorithm.java index 19e68c0531..72d2ae7da2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/DegreeCentralityAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/DegreeCentralityAlgorithm.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/StressCentralityAlgorithmV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/StressCentralityAlgorithmV2.java index d1c3da6d8d..e0614a42aa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/StressCentralityAlgorithmV2.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/cent/StressCentralityAlgorithmV2.java @@ -22,8 +22,8 @@ import java.util.Map; import org.apache.commons.lang3.mutable.MutableLong; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.BfsTraverser; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/KCoreAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/KCoreAlgorithm.java index eb334e5cbe..f0c9502109 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/KCoreAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/KCoreAlgorithm.java @@ -27,7 +27,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.traversal.algorithm.FusiformSimilarityTraverser; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LouvainTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LouvainTraverser.java index d30e798d41..6ac8022685 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LouvainTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LouvainTraverser.java @@ -38,17 +38,17 @@ import org.apache.commons.lang.mutable.MutableFloat; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.iterator.ListIterator; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.AbstractAlgorithm; import org.apache.hugegraph.job.algorithm.AbstractAlgorithm.AlgoTraverser; import org.apache.hugegraph.job.algorithm.Consumers; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LpaAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LpaAlgorithm.java index 4b2e30db3e..e729d378e8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LpaAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/LpaAlgorithm.java @@ -26,10 +26,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.lang3.mutable.MutableInt; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.process.traversal.Scope; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/TriangleCountAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/TriangleCountAlgorithm.java index 3e5c6c6370..411a730008 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/TriangleCountAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/TriangleCountAlgorithm.java @@ -24,8 +24,8 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.lang.mutable.MutableLong; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/WeakConnectedComponent.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/WeakConnectedComponent.java index 674ec50235..25dab78af4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/WeakConnectedComponent.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/comm/WeakConnectedComponent.java @@ -23,10 +23,10 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/path/RingsDetectAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/path/RingsDetectAlgorithm.java index f4e069c252..4bf53ae2bc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/path/RingsDetectAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/path/RingsDetectAlgorithm.java @@ -20,7 +20,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.AbstractAlgorithm; import org.apache.hugegraph.job.algorithm.Consumers.StopExecution; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/rank/PageRankAlgorithm.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/rank/PageRankAlgorithm.java index a7a189ea31..0d70bfaae3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/rank/PageRankAlgorithm.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/algorithm/rank/PageRankAlgorithm.java @@ -23,11 +23,11 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.job.UserJob; import org.apache.hugegraph.job.algorithm.comm.AbstractCommAlgorithm; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/computer/AbstractComputer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/computer/AbstractComputer.java index 5158ec7916..cb7e764f22 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/computer/AbstractComputer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/computer/AbstractComputer.java @@ -32,7 +32,7 @@ import org.apache.commons.configuration2.tree.ImmutableNode; import org.apache.commons.configuration2.tree.NodeHandler; import org.apache.commons.configuration2.tree.NodeModel; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.job.ComputerJob; import org.apache.hugegraph.job.Job; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/EdgeLabelRemoveJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/EdgeLabelRemoveJob.java index 00462b9d78..e9963805fe 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/EdgeLabelRemoveJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/EdgeLabelRemoveJob.java @@ -20,10 +20,10 @@ import java.util.Set; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.type.define.SchemaStatus; import org.apache.hugegraph.util.LockUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRebuildJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRebuildJob.java index 9bf0142d76..0a0e198524 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRebuildJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRebuildJob.java @@ -22,14 +22,14 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.SchemaStatus; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRemoveJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRemoveJob.java index a8d8e1578d..2331202562 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRemoveJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/IndexLabelRemoveJob.java @@ -18,10 +18,10 @@ package org.apache.hugegraph.job.schema; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; import org.apache.hugegraph.type.define.SchemaStatus; import org.apache.hugegraph.util.LockUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyClearJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyClearJob.java index e82ca0c0a6..377b68a8be 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyClearJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyClearJob.java @@ -18,10 +18,10 @@ package org.apache.hugegraph.job.schema; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; import org.apache.hugegraph.type.define.SchemaStatus; import org.apache.hugegraph.util.LockUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyCreateJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyCreateJob.java index 483b9106f8..367960e1aa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyCreateJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyCreateJob.java @@ -18,7 +18,7 @@ package org.apache.hugegraph.job.schema; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; public class OlapPropertyKeyCreateJob extends SchemaJob { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyRemoveJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyRemoveJob.java index e6f5f20e0c..6b9b5471f4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyRemoveJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/OlapPropertyKeyRemoveJob.java @@ -17,9 +17,9 @@ package org.apache.hugegraph.job.schema; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; public class OlapPropertyKeyRemoveJob extends OlapPropertyKeyClearJob { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/SchemaJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/SchemaJob.java index 3165351396..01d456f368 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/SchemaJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/SchemaJob.java @@ -20,11 +20,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.tx.ISchemaTransaction; import org.apache.hugegraph.job.SysJob; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/VertexLabelRemoveJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/VertexLabelRemoveJob.java index 90bc469124..4c95840321 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/VertexLabelRemoveJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/schema/VertexLabelRemoveJob.java @@ -20,13 +20,13 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.backend.tx.ISchemaTransaction; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.define.SchemaStatus; import org.apache.hugegraph.util.LockUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredIndexJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredIndexJob.java index 5556febb89..459b8de465 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredIndexJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredIndexJob.java @@ -21,10 +21,10 @@ import java.util.Set; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.query.IdQuery; +import org.apache.hugegraph.query.IdQuery; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; @@ -32,9 +32,9 @@ public class DeleteExpiredIndexJob extends DeleteExpiredJob { private static final String JOB_TYPE = "delete_expired_index"; - private final Set indexes; + private final Set indexes; - public DeleteExpiredIndexJob(Set indexes) { + public DeleteExpiredIndexJob(Set indexes) { E.checkArgument(indexes != null && !indexes.isEmpty(), "The indexes can't be null or empty"); this.indexes = indexes; @@ -52,7 +52,7 @@ public V execute() throws Exception { HugeGraphParams graph = this.params(); GraphTransaction tx = graph.graphTransaction(); try { - for (HugeIndex index : this.indexes) { + for (Index index : this.indexes) { this.deleteExpiredIndex(graph, index); } tx.commit(); @@ -70,7 +70,7 @@ public V execute() throws Exception { * Delete expired element(if exist) of the index, * otherwise just delete expired index only */ - private void deleteExpiredIndex(HugeGraphParams graph, HugeIndex index) { + private void deleteExpiredIndex(HugeGraphParams graph, Index index) { GraphTransaction tx = graph.graphTransaction(); HugeType type = index.indexLabel().queryType().isVertex() ? HugeType.VERTEX : HugeType.EDGE; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredJob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredJob.java index 9ffa9e955b..28f4012c88 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredJob.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/DeleteExpiredJob.java @@ -23,7 +23,7 @@ import org.apache.hugegraph.job.EphemeralJobBuilder; import org.apache.hugegraph.job.system.JobCounters.JobCounter; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; @@ -80,7 +80,7 @@ public static EphemeralJob newDeleteExpiredElementJob( if (object instanceof HugeElement) { return new DeleteExpiredElementJob<>(jobCounter.elements()); } else { - assert object instanceof HugeIndex; + assert object instanceof Index; return new DeleteExpiredIndexJob<>(jobCounter.indexes()); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/JobCounters.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/JobCounters.java index 6feed5699c..848a821058 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/JobCounters.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/job/system/JobCounters.java @@ -24,7 +24,7 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.structure.HugeElement; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.Index; public class JobCounters { @@ -43,7 +43,7 @@ public static class JobCounter { private final AtomicInteger jobs; private Set elements; - private Set indexes; + private Set indexes; private final int batchSize; public JobCounter(int batchSize) { @@ -69,7 +69,7 @@ public Set elements() { return this.elements; } - public Set indexes() { + public Set indexes() { return this.indexes; } @@ -77,7 +77,7 @@ public void clear(Object object) { if (object instanceof HugeElement) { this.elements = ConcurrentHashMap.newKeySet(); } else { - assert object instanceof HugeIndex; + assert object instanceof Index; this.indexes = ConcurrentHashMap.newKeySet(); } } @@ -85,7 +85,7 @@ public void clear(Object object) { public boolean addAndTriggerDelete(Object object) { return object instanceof HugeElement ? addElementAndTriggerDelete((HugeElement) object) : - addIndexAndTriggerDelete((HugeIndex) object); + addIndexAndTriggerDelete((Index) object); } /** @@ -108,7 +108,7 @@ public boolean addElementAndTriggerDelete(HugeElement element) { * @param index * @return true if we should create a new delete job, false otherwise */ - public boolean addIndexAndTriggerDelete(HugeIndex index) { + public boolean addIndexAndTriggerDelete(Index index) { if (this.indexes.size() >= this.batchSize) { return true; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sDriver.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sDriver.java index 47a34658fd..61b3340fdc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sDriver.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sDriver.java @@ -31,7 +31,7 @@ import io.fabric8.kubernetes.client.dsl.ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable; import io.fabric8.kubernetes.client.dsl.Resource; import org.apache.commons.io.FileUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.space.GraphSpace; import org.apache.hugegraph.space.Service; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sManager.java index 11db1adf32..1e3057c860 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sManager.java @@ -19,7 +19,7 @@ import com.google.common.base.Strings; import io.fabric8.kubernetes.api.model.Namespace; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.space.GraphSpace; import org.apache.hugegraph.space.Service; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sRegister.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sRegister.java index c1dd29abc8..73701f463e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sRegister.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/k8s/K8sRegister.java @@ -23,7 +23,7 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/kvstore/KvStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/kvstore/KvStore.java index 569af417f4..94ed2a32a7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/kvstore/KvStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/kvstore/KvStore.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Map; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.tinkerpop.gremlin.structure.Vertex; public interface KvStore { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/masterelection/GlobalMasterInfo.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/masterelection/GlobalMasterInfo.java index ef7c2f338d..668c0413f6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/masterelection/GlobalMasterInfo.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/masterelection/GlobalMasterInfo.java @@ -17,8 +17,8 @@ package org.apache.hugegraph.masterelection; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.type.define.NodeRole; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java index 976b9cb373..e05d50326c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java @@ -17,13 +17,15 @@ package org.apache.hugegraph.memory.consumer.factory; +import org.apache.hugegraph.backend.BinaryId; + import java.util.UUID; import org.apache.hugegraph.backend.cache.CachedBackendStore; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.consumer.OffHeapObject; @@ -50,7 +52,7 @@ private IdFactory() { /** * If using off-heap mode, param id must be OffHeapObject */ - public BinaryBackendEntry.BinaryId newBinaryId(byte[] bytes, Id id) { + public BinaryId newBinaryId(byte[] bytes, Id id) { switch (memoryMode) { case ENABLE_ON_HEAP_MANAGEMENT: case ENABLE_OFF_HEAP_MANAGEMENT: @@ -63,7 +65,7 @@ public BinaryBackendEntry.BinaryId newBinaryId(byte[] bytes, Id id) { (OffHeapObject) id); case DISABLE_MEMORY_MANAGEMENT: default: - return new BinaryBackendEntry.BinaryId(bytes, id); + return new BinaryId(bytes, id); } } @@ -238,8 +240,8 @@ public EdgeId newEdgeId(HugeVertex ownerVertex, ); case DISABLE_MEMORY_MANAGEMENT: default: - return new EdgeId(ownerVertex, direction, edgeLabelId, subLabelId, sortValues, - otherVertex); + return new EdgeId(ownerVertex.id(), direction, edgeLabelId, subLabelId, sortValues, + otherVertex.id()); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java index c628155eb1..896e25248a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -24,7 +24,7 @@ import org.apache.hugegraph.memory.consumer.impl.property.HugeEdgePropertyOffHeap; import org.apache.hugegraph.memory.consumer.impl.property.HugeVertexPropertyOffHeap; import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.structure.HugeVertexProperty; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java index e6444f3061..448c76aa08 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -20,8 +20,8 @@ import java.util.Collections; import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.backend.BinaryId; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.util.Bytes; @@ -30,7 +30,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class BinaryIdOffHeap extends BinaryBackendEntry.BinaryId implements OffHeapObject { +public class BinaryIdOffHeap extends BinaryId implements OffHeapObject { private final OffHeapObject originId; private ByteBuf bytesOffHeap; @@ -51,8 +51,8 @@ public void serializeSelfToByteBuf(MemoryPool memoryPool) { } @Override - public BinaryBackendEntry.BinaryId zeroCopyReadFromByteBuf() { - return new BinaryBackendEntry.BinaryId(ByteBufUtil.getBytes(bytesOffHeap), + public BinaryId zeroCopyReadFromByteBuf() { + return new BinaryId(ByteBufUtil.getBytes(bytesOffHeap), (Id) originId.zeroCopyReadFromByteBuf()); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index b77de337a8..502e8286e0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -22,10 +22,8 @@ import java.util.List; import java.util.Objects; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdUtil; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.structure.HugeVertex; @@ -57,7 +55,7 @@ public EdgeIdOffHeap(HugeVertex ownerVertex, OffHeapObject edgeLabelIdOffHeap, OffHeapObject subLabelIdOffHeap, OffHeapObject otherVertexIdOffHeap) { - super(ownerVertex, direction, edgeLabelId, subLabelId, sortValues, otherVertex); + super(ownerVertex.id(), direction, edgeLabelId, subLabelId, sortValues, otherVertex.id()); this.memoryPool = memoryPool; this.ownerVertexIdOffHeap = ownerVertexIdOffHeap; this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; @@ -220,23 +218,7 @@ public String asString() { this.cacheOffHeap.resetReaderIndex(); } } - String tmpCache; - if (this.directed) { - tmpCache = SplicingIdGenerator.concat( - IdUtil.writeString((Id) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf()), - this.direction.type().string(), - IdUtil.writeLong((Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf()), - IdUtil.writeLong((Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf()), - this.sortValues(), - IdUtil.writeString((Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf())); - } else { - tmpCache = SplicingIdGenerator.concat( - IdUtil.writeString((Id) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf()), - IdUtil.writeLong((Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf()), - IdUtil.writeLong((Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf()), - this.sortValues(), - IdUtil.writeString((Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf())); - } + String tmpCache = this.formatString(); byte[] tmpCacheBytes = tmpCache.getBytes(StandardCharsets.UTF_8); this.cacheOffHeap = (ByteBuf) memoryPool.requireMemory(tmpCacheBytes.length, memoryPool); this.cacheOffHeap.markReaderIndex(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java index 8d86f84a88..b7e34f28a1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -17,14 +17,14 @@ package org.apache.hugegraph.memory.consumer.impl.id; -import static org.apache.hugegraph.backend.id.IdGenerator.compareType; +import static org.apache.hugegraph.id.IdGenerator.compareType; import java.util.Collections; import java.util.List; import java.util.Objects; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.util.NumericUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index d47d955a4d..16ab09a13b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.Objects; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.FurySerializationUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java index 8a8dd4d1ee..4b7c539b79 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -22,8 +22,8 @@ import java.util.List; import org.apache.hugegraph.backend.cache.CachedBackendStore; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java index d026583821..cb8295fe31 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -17,14 +17,14 @@ package org.apache.hugegraph.memory.consumer.impl.id; -import static org.apache.hugegraph.backend.id.IdGenerator.compareType; +import static org.apache.hugegraph.id.IdGenerator.compareType; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.jetbrains.annotations.TestOnly; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java index ed4b0399b5..e2af7ea1c7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -17,16 +17,16 @@ package org.apache.hugegraph.memory.consumer.impl.id; -import static org.apache.hugegraph.backend.id.IdGenerator.compareType; +import static org.apache.hugegraph.id.IdGenerator.compareType; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.UUID; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.FurySerializationUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java index d2f21a414c..bec26eb672 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -24,10 +24,11 @@ import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.FurySerializationUtil; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.structure.BaseProperty; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; @@ -53,7 +54,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { - byte[] bytes = FurySerializationUtil.FURY.serialize(this.value); + byte[] bytes = FurySerializationUtil.FURY.serialize(this.property.value()); this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.valueOffHeap.markReaderIndex(); this.valueOffHeap.writeBytes(bytes); @@ -61,7 +62,12 @@ public void serializeSelfToByteBuf(MemoryPool memoryPool) { @Override public void releaseOriginalVarsOnHeap() { - this.value = null; + this.property = new BaseProperty(this.pkey, null) { + @Override + public V value() { + return HugeEdgePropertyOffHeap.this.value(); + } + }; } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java index 1beb759cf0..0c75e44608 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -24,8 +24,9 @@ import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.FurySerializationUtil; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.structure.BaseProperty; import org.apache.hugegraph.structure.HugeVertexProperty; import io.netty.buffer.ByteBuf; @@ -52,7 +53,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { - byte[] bytes = FurySerializationUtil.FURY.serialize(this.value); + byte[] bytes = FurySerializationUtil.FURY.serialize(this.property.value()); this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.valueOffHeap.markReaderIndex(); this.valueOffHeap.writeBytes(bytes); @@ -60,7 +61,12 @@ public void serializeSelfToByteBuf(MemoryPool memoryPool) { @Override public void releaseOriginalVarsOnHeap() { - this.value = null; + this.property = new BaseProperty(this.pkey, null) { + @Override + public V value() { + return HugeVertexPropertyOffHeap.this.value(); + } + }; } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java index a63ddc91b7..3c726dea9a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java @@ -17,32 +17,16 @@ package org.apache.hugegraph.memory.util; -import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.hugegraph.util.UnsafeUtil; import sun.misc.Unsafe; // NOTE: due to different layout of klass in various versions of JDK, this class may easily crash! public class OffHeapMemoryUtil { - private static final Logger LOG = LoggerFactory.getLogger(OffHeapMemoryUtil.class); - private static final Unsafe UNSAFE; - - static { - Unsafe unsafe; - try { - Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - unsafe = (Unsafe) unsafeField.get(null); - } catch (Throwable cause) { - LOG.warn("sun.misc.Unsafe.theUnsafe: unavailable.", cause); - throw new UnsupportedOperationException("Unsafe is not supported in this platform."); - } - UNSAFE = unsafe; - } + private static final Unsafe UNSAFE = UnsafeUtil.getUnsafe(); public static long allocateObjectToOffHeap(Object obj) { long size = sizeOf(obj); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java index c770752626..152e2f92cc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java @@ -16,7 +16,7 @@ */ package org.apache.hugegraph.memory.util; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public class OutOfMemoryException extends HugeException { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/EtcdMetaDriver.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/EtcdMetaDriver.java index 75042131c8..6af98e0a88 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/EtcdMetaDriver.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/EtcdMetaDriver.java @@ -31,7 +31,7 @@ import java.util.function.Consumer; import org.apache.commons.io.FileUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.meta.lock.EtcdDistributedLock; import org.apache.hugegraph.meta.lock.LockResult; import org.apache.hugegraph.type.define.CollectionType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/MetaManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/MetaManager.java index b30b505d32..0bc917d78d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/MetaManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/MetaManager.java @@ -36,8 +36,8 @@ import org.apache.hugegraph.auth.HugeRole; import org.apache.hugegraph.auth.HugeTarget; import org.apache.hugegraph.auth.HugeUser; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.meta.lock.LockResult; import org.apache.hugegraph.meta.managers.AuthMetaManager; import org.apache.hugegraph.meta.managers.ConfigMetaManager; @@ -49,10 +49,10 @@ import org.apache.hugegraph.meta.managers.ServiceMetaManager; import org.apache.hugegraph.meta.managers.SpaceMetaManager; import org.apache.hugegraph.meta.managers.TaskMetaManager; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.space.GraphSpace; import org.apache.hugegraph.space.SchemaTemplate; import org.apache.hugegraph.space.Service; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/PdMetaDriver.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/PdMetaDriver.java index 18d0ea3fc3..c744e02e8e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/PdMetaDriver.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/PdMetaDriver.java @@ -23,7 +23,7 @@ import java.util.Map; import java.util.function.Consumer; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.constant.ServiceConstant; import org.apache.hugegraph.meta.lock.LockResult; import org.apache.hugegraph.meta.lock.PdDistributedLock; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/lock/PdDistributedLock.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/lock/PdDistributedLock.java index 3e8c66ea14..2dbbdffdd0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/lock/PdDistributedLock.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/lock/PdDistributedLock.java @@ -22,7 +22,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.pd.client.KvClient; import org.apache.hugegraph.pd.common.PDException; import org.apache.hugegraph.pd.grpc.kv.LockResponse; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AbstractMetaManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AbstractMetaManager.java index b7294a36e2..b1930144c0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AbstractMetaManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AbstractMetaManager.java @@ -26,11 +26,11 @@ import java.util.function.Consumer; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.auth.SchemaDefine; import org.apache.hugegraph.meta.MetaDriver; import org.apache.hugegraph.meta.lock.LockResult; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.util.JsonUtil; public class AbstractMetaManager { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManager.java index bf801c0849..5e5c3c0bc1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManager.java @@ -47,8 +47,8 @@ import org.apache.hugegraph.auth.HugeRole; import org.apache.hugegraph.auth.HugeTarget; import org.apache.hugegraph.auth.HugeUser; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.meta.MetaDriver; import org.apache.hugegraph.meta.MetaManager; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaMetaManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaMetaManager.java index 57e2839837..e832fb50a6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaMetaManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaMetaManager.java @@ -33,14 +33,14 @@ import java.util.Map; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.meta.MetaDriver; import org.apache.hugegraph.meta.PdMetaDriver; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.util.JsonUtil; public class SchemaMetaManager extends AbstractMetaManager { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaTemplateMetaManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaTemplateMetaManager.java index bc2f1448bc..0fa8a0328a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaTemplateMetaManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/meta/managers/SchemaTemplateMetaManager.java @@ -27,7 +27,7 @@ import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.meta.MetaDriver; import org.apache.hugegraph.space.SchemaTemplate; import org.apache.hugegraph.util.JsonUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/plugin/HugeGraphGremlinPlugin.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/plugin/HugeGraphGremlinPlugin.java index 0b3b19ba7e..8ae5c80096 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/plugin/HugeGraphGremlinPlugin.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/plugin/HugeGraphGremlinPlugin.java @@ -22,7 +22,7 @@ import java.util.Iterator; import java.util.Set; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.util.ReflectionUtil; import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinPlugin; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java deleted file mode 100644 index 52c86bb7d7..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.rpc; - -public interface RpcServiceConfig4Client { - - T serviceProxy(String interfaceId); - - T serviceProxy(String graph, String interfaceId); - - default T serviceProxy(Class clazz) { - return this.serviceProxy(clazz.getName()); - } - - default T serviceProxy(String graph, Class clazz) { - return this.serviceProxy(graph, clazz.getName()); - } - - void removeAllServiceProxy(); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java deleted file mode 100644 index 4648244734..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.rpc; - -public interface RpcServiceConfig4Server { - - String addService(Class clazz, S serviceImpl); - - String addService(String graph, Class clazz, - S serviceImpl); - - void removeService(String serviceId); - - void removeAllService(); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java deleted file mode 100644 index da572321c1..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.builder.SchemaBuilder; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.Directions; -import org.apache.hugegraph.type.define.EdgeLabelType; -import org.apache.hugegraph.type.define.Frequency; -import org.apache.hugegraph.type.define.SchemaStatus; -import org.apache.hugegraph.util.E; - -import com.google.common.base.Objects; - -public class EdgeLabel extends SchemaLabel { - - public static final EdgeLabel NONE = new EdgeLabel(null, NONE_ID, UNDEF); - - private Set> links = new HashSet<>(); - private Id sourceLabel = NONE_ID; - private Id targetLabel = NONE_ID; - private Frequency frequency; - private List sortKeys; - - private EdgeLabelType edgeLabelType = EdgeLabelType.NORMAL; - private Id fatherId; - - public EdgeLabel(final HugeGraph graph, Id id, String name) { - super(graph, id, name); - this.frequency = Frequency.DEFAULT; - this.sortKeys = new ArrayList<>(); - } - - @Override - public HugeType type() { - return HugeType.EDGE_LABEL; - } - - public boolean isFather() { - return this.edgeLabelType.parent(); - } - - public void edgeLabelType(EdgeLabelType type) { - this.edgeLabelType = type; - } - - public EdgeLabelType edgeLabelType() { - return this.edgeLabelType; - } - - public boolean hasFather() { - return this.edgeLabelType.sub(); - } - - public Id fatherId() { - return this.fatherId; - } - - public void fatherId(Id fatherId) { - this.fatherId = fatherId; - } - - public Frequency frequency() { - return this.frequency; - } - - public void frequency(Frequency frequency) { - this.frequency = frequency; - } - - public boolean directed() { - // TODO: implement (do we need this method?) - return true; - } - - public String sourceLabelName() { - E.checkState(this.links.size() == 1, - "Only edge label has single vertex label pair can call " + - "sourceLabelName(), but current edge label got %s", - this.links.size()); - return this.graph.vertexLabelOrNone(this.links.iterator().next().getLeft()).name(); - } - - public List linksIds() { - List ids = new ArrayList<>(this.links.size() * 2); - for (Pair link : this.links) { - ids.add(link.getLeft()); - ids.add(link.getRight()); - } - return ids; - } - - public void linksIds(Id[] ids) { - this.links = new HashSet<>(ids.length / 2); - for (int i = 0; i < ids.length; i += 2) { - this.links.add(Pair.of(ids[i], ids[i + 1])); - } - } - - public Id sourceLabel() { - if (links.size() == 1) { - return links.iterator().next().getLeft(); - } - return NONE_ID; - } - - public void sourceLabel(Id id) { - E.checkArgument(this.links.isEmpty(), - "Not allowed add source label to an edge label which " + - "already has links"); - if (this.targetLabel != NONE_ID) { - this.links.add(Pair.of(id, this.targetLabel)); - this.targetLabel = NONE_ID; - } else { - this.sourceLabel = id; - } - } - - public String targetLabelName() { - E.checkState(this.links.size() == 1, - "Only edge label has single vertex label pair can call " + - "sourceLabelName(), but current edge label got %s", - this.links.size()); - return this.graph.vertexLabelOrNone(this.links.iterator().next().getRight()).name(); - } - - public Id targetLabel() { - if (links.size() == 1) { - return links.iterator().next().getRight(); - } - return NONE_ID; - } - - public void targetLabel(Id id) { - E.checkArgument(this.links.isEmpty(), - "Not allowed add source label to an edge label which " + - "already has links"); - if (this.sourceLabel != NONE_ID) { - this.links.add(Pair.of(this.sourceLabel, id)); - this.sourceLabel = NONE_ID; - } else { - this.targetLabel = id; - } - } - - public boolean linkWithLabel(Id id) { - for (Pair link : this.links) { - if (link.getLeft().equals(id) || link.getRight().equals(id)) { - return true; - } - } - return false; - } - - public boolean linkWithVertexLabel(Id label, Directions dir) { - return this.links.stream().anyMatch(pair -> { - Id sourceLabel = pair.getLeft(); - Id targetLabel = pair.getRight(); - if (dir.equals(Directions.IN)) { - return targetLabel.equals(label); - } else if (dir.equals(Directions.OUT)) { - return sourceLabel.equals(label); - } else if (dir.equals(Directions.BOTH)) { - return targetLabel.equals(label) || sourceLabel.equals(label); - } - return false; - }); - } - - public boolean checkLinkEqual(Id sourceLabel, Id targetLabel) { - return this.links.contains(Pair.of(sourceLabel, targetLabel)); - } - - public Set> links() { - return this.links; - } - - public void links(Pair link) { - if (this.links == null) { - this.links = new HashSet<>(); - } - this.links.add(link); - } - - public boolean existSortKeys() { - return !this.sortKeys.isEmpty(); - } - - public List sortKeys() { - return Collections.unmodifiableList(this.sortKeys); - } - - public void sortKey(Id id) { - this.sortKeys.add(id); - } - - public void sortKeys(Id... ids) { - this.sortKeys.addAll(Arrays.asList(ids)); - } - - public boolean hasSameContent(EdgeLabel other) { - return super.hasSameContent(other) && - this.frequency == other.frequency && - Objects.equal(this.sourceLabelName(), other.sourceLabelName()) && - Objects.equal(this.targetLabelName(), other.targetLabelName()) && - Objects.equal(this.graph.mapPkId2Name(this.sortKeys), - other.graph.mapPkId2Name(other.sortKeys)); - } - - public static EdgeLabel undefined(HugeGraph graph, Id id) { - return new EdgeLabel(graph, id, UNDEF); - } - - public interface Builder extends SchemaBuilder { - - Id rebuildIndex(); - - Builder asBase(); - - Builder withBase(String fatherLabel); - - Builder link(String sourceLabel, String targetLabel); - - @Deprecated - Builder sourceLabel(String label); - - @Deprecated - Builder targetLabel(String label); - - Builder singleTime(); - - Builder multiTimes(); - - Builder sortKeys(String... keys); - - Builder properties(String... properties); - - Builder nullableKeys(String... keys); - - Builder frequency(Frequency frequency); - - Builder ttl(long ttl); - - Builder ttlStartTime(String ttlStartTime); - - Builder enableLabelIndex(boolean enable); - - Builder userdata(String key, Object value); - - Builder userdata(Map userdata); - } - - @Override - public Map asMap() { - Map map = new HashMap<>(); - - if (this.sourceLabel() != null && this.sourceLabel() != NONE_ID) { - map.put(P.SOURCE_LABEL, this.sourceLabel().asString()); - } - - if (this.targetLabel() != null && this.targetLabel() != NONE_ID) { - map.put(P.TARGET_LABEL, this.targetLabel().asString()); - } - - if (this.properties() != null) { - map.put(P.PROPERTIES, this.properties()); - } - - if (this.nullableKeys() != null) { - map.put(P.NULLABLE_KEYS, this.nullableKeys()); - } - - if (this.indexLabels() != null) { - map.put(P.INDEX_LABELS, this.indexLabels()); - } - - if (this.ttlStartTime() != null) { - map.put(P.TT_START_TIME, this.ttlStartTime().asString()); - } - - if (this.sortKeys() != null) { - map.put(P.SORT_KEYS, this.sortKeys); - } - - map.put(P.EDGELABEL_TYPE, this.edgeLabelType); - if (this.fatherId() != null) { - map.put(P.FATHER_ID, this.fatherId().asString()); - } - map.put(P.ENABLE_LABEL_INDEX, this.enableLabelIndex()); - map.put(P.TTL, String.valueOf(this.ttl())); - map.put(P.LINKS, this.links()); - map.put(P.FREQUENCY, this.frequency().toString()); - - return super.asMap(map); - } - - @SuppressWarnings("unchecked") - public static EdgeLabel fromMap(Map map, HugeGraph graph) { - Id id = IdGenerator.of((int) map.get(EdgeLabel.P.ID)); - String name = (String) map.get(EdgeLabel.P.NAME); - EdgeLabel edgeLabel = new EdgeLabel(graph, id, name); - for (Map.Entry entry : map.entrySet()) { - switch (entry.getKey()) { - case P.ID: - case P.NAME: - break; - case P.STATUS: - edgeLabel.status( - SchemaStatus.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.USERDATA: - edgeLabel.userdata(new Userdata((Map) entry.getValue())); - break; - case P.PROPERTIES: - Set ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - edgeLabel.properties(ids); - break; - case P.NULLABLE_KEYS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - edgeLabel.nullableKeys(ids); - break; - case P.INDEX_LABELS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - edgeLabel.addIndexLabels(ids.toArray(new Id[0])); - break; - case P.ENABLE_LABEL_INDEX: - boolean enableLabelIndex = (Boolean) entry.getValue(); - edgeLabel.enableLabelIndex(enableLabelIndex); - break; - case P.TTL: - long ttl = Long.parseLong((String) entry.getValue()); - edgeLabel.ttl(ttl); - break; - case P.TT_START_TIME: - long ttlStartTime = - Long.parseLong((String) entry.getValue()); - edgeLabel.ttlStartTime(IdGenerator.of(ttlStartTime)); - break; - case P.LINKS: - // TODO: serialize and deserialize - List list = (List) entry.getValue(); - for (Map m : list) { - for (Object key : m.keySet()) { - Id sid = IdGenerator.of(Long.parseLong((String) key)); - Id tid = IdGenerator.of(Long.parseLong(String.valueOf(m.get(key)))); - edgeLabel.links(Pair.of(sid, tid)); - } - } - break; - case P.SOURCE_LABEL: - long sourceLabel = - Long.parseLong((String) entry.getValue()); - edgeLabel.sourceLabel(IdGenerator.of(sourceLabel)); - break; - case P.TARGET_LABEL: - long targetLabel = - Long.parseLong((String) entry.getValue()); - edgeLabel.targetLabel(IdGenerator.of(targetLabel)); - break; - case P.FATHER_ID: - long fatherId = - Long.parseLong((String) entry.getValue()); - edgeLabel.fatherId(IdGenerator.of(fatherId)); - break; - case P.EDGELABEL_TYPE: - EdgeLabelType edgeLabelType = - EdgeLabelType.valueOf( - ((String) entry.getValue()).toUpperCase()); - edgeLabel.edgeLabelType(edgeLabelType); - break; - case P.FREQUENCY: - Frequency frequency = - Frequency.valueOf(((String) entry.getValue()).toUpperCase()); - edgeLabel.frequency(frequency); - break; - case P.SORT_KEYS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - edgeLabel.sortKeys(ids.toArray(new Id[0])); - break; - default: - throw new AssertionError(String.format( - "Invalid key '%s' for edge label", - entry.getKey())); - } - } - return edgeLabel; - } - - public static final class P { - - public static final String ID = "id"; - public static final String NAME = "name"; - - public static final String STATUS = "status"; - public static final String USERDATA = "userdata"; - - public static final String PROPERTIES = "properties"; - public static final String NULLABLE_KEYS = "nullableKeys"; - public static final String INDEX_LABELS = "indexLabels"; - - public static final String ENABLE_LABEL_INDEX = "enableLabelIndex"; - public static final String TTL = "ttl"; - public static final String TT_START_TIME = "ttlStartTime"; - public static final String LINKS = "links"; - public static final String SOURCE_LABEL = "sourceLabel"; - public static final String TARGET_LABEL = "targetLabel"; - public static final String EDGELABEL_TYPE = "edgeLabelType"; - public static final String FATHER_ID = "fatherId"; - public static final String FREQUENCY = "frequency"; - public static final String SORT_KEYS = "sortKeys"; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/IndexLabel.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/IndexLabel.java deleted file mode 100644 index e20a728c2b..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/IndexLabel.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.builder.SchemaBuilder; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.IndexType; -import org.apache.hugegraph.type.define.SchemaStatus; -import org.apache.hugegraph.util.E; - -import com.google.common.base.Objects; - -public class IndexLabel extends SchemaElement { - - private HugeType baseType; - private Id baseValue; - private IndexType indexType; - private List indexFields; - - public IndexLabel(final HugeGraph graph, Id id, String name) { - super(graph, id, name); - this.baseType = HugeType.SYS_SCHEMA; - this.baseValue = NONE_ID; - this.indexType = IndexType.SECONDARY; - this.indexFields = new ArrayList<>(); - } - - protected IndexLabel(long id, String name) { - this(null, IdGenerator.of(id), name); - } - - @Override - public HugeType type() { - return HugeType.INDEX_LABEL; - } - - public HugeType baseType() { - return this.baseType; - } - - public void baseType(HugeType baseType) { - this.baseType = baseType; - } - - public Id baseValue() { - return this.baseValue; - } - - public void baseValue(Id id) { - this.baseValue = id; - } - - public IndexType indexType() { - return this.indexType; - } - - public void indexType(IndexType indexType) { - this.indexType = indexType; - } - - public HugeType queryType() { - switch (this.baseType) { - case VERTEX_LABEL: - return HugeType.VERTEX; - case EDGE_LABEL: - return HugeType.EDGE; - case SYS_SCHEMA: - return HugeType.SYS_SCHEMA; - default: - throw new AssertionError(String.format( - "Query type of index label is either '%s' or '%s', " + - "but '%s' is used", - HugeType.VERTEX_LABEL, HugeType.EDGE_LABEL, - this.baseType)); - } - } - - public List indexFields() { - return Collections.unmodifiableList(this.indexFields); - } - - public void indexFields(Id... ids) { - this.indexFields.addAll(Arrays.asList(ids)); - } - - public void indexField(Id id) { - this.indexFields.add(id); - } - - public Id indexField() { - E.checkState(this.indexFields.size() == 1, - "There should be only one field in %s index label, " + - "but got: %s", this.indexType.string(), this.indexFields); - return this.indexFields.get(0); - } - - public SchemaLabel baseLabel() { - return getBaseLabel(this.graph, this.baseType, this.baseValue); - } - - public boolean hasSameContent(IndexLabel other) { - return super.hasSameContent(other) && - this.indexType == other.indexType && - this.baseType == other.baseType && - Objects.equal(this.graph.mapPkId2Name(this.indexFields), - other.graph.mapPkId2Name(other.indexFields)); - } - - public boolean olap() { - return VertexLabel.OLAP_VL.id().equals(this.baseValue); - } - - public Object validValue(Object value) { - if (!(value instanceof Number)) { - return value; - } - - Number number = (Number) value; - switch (this.indexType()) { - case RANGE_INT: - return number.intValue(); - case RANGE_LONG: - return number.longValue(); - case RANGE_FLOAT: - return number.floatValue(); - case RANGE_DOUBLE: - return number.doubleValue(); - default: - return value; - } - } - - // Label index - private static final IndexLabel VL_IL = new IndexLabel(VL_IL_ID, "~vli"); - private static final IndexLabel EL_IL = new IndexLabel(EL_IL_ID, "~eli"); - - // Schema name index - private static final IndexLabel PKN_IL = new IndexLabel(PKN_IL_ID, "~pkni"); - private static final IndexLabel VLN_IL = new IndexLabel(VLN_IL_ID, "~vlni"); - private static final IndexLabel ELN_IL = new IndexLabel(ELN_IL_ID, "~elni"); - private static final IndexLabel ILN_IL = new IndexLabel(ILN_IL_ID, "~ilni"); - - public static IndexLabel label(HugeType type) { - switch (type) { - case TASK: - case SERVER: - case VERTEX: - return VL_IL; - case EDGE: - case EDGE_OUT: - case EDGE_IN: - return EL_IL; - case PROPERTY_KEY: - return PKN_IL; - case VERTEX_LABEL: - return VLN_IL; - case EDGE_LABEL: - return ELN_IL; - case INDEX_LABEL: - return ILN_IL; - default: - throw new AssertionError(String.format( - "No primitive index label for '%s'", type)); - } - } - - public static IndexLabel label(HugeGraph graph, Id id) { - // Primitive IndexLabel first - if (id.asLong() < 0 && id.asLong() > -NEXT_PRIMITIVE_SYS_ID) { - switch ((int) id.asLong()) { - case VL_IL_ID: - return VL_IL; - case EL_IL_ID: - return EL_IL; - case PKN_IL_ID: - return PKN_IL; - case VLN_IL_ID: - return VLN_IL; - case ELN_IL_ID: - return ELN_IL; - case ILN_IL_ID: - return ILN_IL; - default: - throw new AssertionError(String.format( - "No primitive index label for '%s'", id)); - } - } - return graph.indexLabel(id); - } - - public static SchemaLabel getBaseLabel(HugeGraph graph, - HugeType baseType, - Object baseValue) { - E.checkNotNull(baseType, "base type", "index label"); - E.checkNotNull(baseValue, "base value", "index label"); - E.checkArgument(baseValue instanceof String || baseValue instanceof Id, - "The base value must be instance of String or Id, " + - "but got %s(%s)", baseValue, - baseValue.getClass().getSimpleName()); - - SchemaLabel label; - switch (baseType) { - case VERTEX_LABEL: - if (baseValue instanceof String) { - label = graph.vertexLabel((String) baseValue); - } else { - assert baseValue instanceof Id; - label = graph.vertexLabel((Id) baseValue); - } - break; - case EDGE_LABEL: - if (baseValue instanceof String) { - label = graph.edgeLabel((String) baseValue); - } else { - assert baseValue instanceof Id; - label = graph.edgeLabel((Id) baseValue); - } - break; - default: - throw new AssertionError(String.format( - "Unsupported base type '%s' of index label", - baseType)); - } - - E.checkArgumentNotNull(label, "Can't find the %s with name '%s'", - baseType.readableName(), baseValue); - return label; - } - - public interface Builder extends SchemaBuilder { - - TaskWithSchema createWithTask(); - - Id rebuild(); - - Builder onV(String baseValue); - - Builder onE(String baseValue); - - Builder by(String... fields); - - Builder secondary(); - - Builder range(); - - Builder search(); - - Builder shard(); - - Builder unique(); - - Builder on(HugeType baseType, String baseValue); - - Builder indexType(IndexType indexType); - - Builder userdata(String key, Object value); - - Builder userdata(Map userdata); - - Builder rebuild(boolean rebuild); - } - - @Override - public Map asMap() { - HashMap map = new HashMap<>(); - map.put(P.BASE_TYPE, this.baseType().name()); - map.put(P.BASE_VALUE, this.baseValue().asString()); - map.put(P.INDEX_TYPE, this.indexType().name()); - map.put(P.INDEX_FIELDS, this.indexFields()); - return super.asMap(map); - } - - @SuppressWarnings("unchecked") - public static IndexLabel fromMap(Map map, HugeGraph graph) { - Id id = IdGenerator.of((int) map.get(IndexLabel.P.ID)); - String name = (String) map.get(IndexLabel.P.NAME); - - IndexLabel indexLabel = new IndexLabel(graph, id, name); - for (Map.Entry entry : map.entrySet()) { - switch (entry.getKey()) { - case P.ID: - case P.NAME: - break; - case P.STATUS: - indexLabel.status( - SchemaStatus.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.USERDATA: - indexLabel.userdata(new Userdata((Map) entry.getValue())); - break; - case P.BASE_TYPE: - HugeType hugeType = - HugeType.valueOf(((String) entry.getValue()).toUpperCase()); - indexLabel.baseType(hugeType); - break; - case P.BASE_VALUE: - long sourceLabel = - Long.parseLong((String) entry.getValue()); - indexLabel.baseValue(IdGenerator.of(sourceLabel)); - break; - case P.INDEX_TYPE: - IndexType indexType = - IndexType.valueOf(((String) entry.getValue()).toUpperCase()); - indexLabel.indexType(indexType); - break; - case P.INDEX_FIELDS: - List ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toList()); - indexLabel.indexFields(ids.toArray(new Id[0])); - break; - default: - throw new AssertionError(String.format( - "Invalid key '%s' for index label", - entry.getKey())); - } - } - return indexLabel; - } - - public static final class P { - - public static final String ID = "id"; - public static final String NAME = "name"; - - public static final String STATUS = "status"; - public static final String USERDATA = "userdata"; - - public static final String BASE_TYPE = "baseType"; - public static final String BASE_VALUE = "baseValue"; - public static final String INDEX_TYPE = "indexType"; - public static final String INDEX_FIELDS = "indexFields"; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/PropertyKey.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/PropertyKey.java deleted file mode 100644 index 5bf34ea530..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/PropertyKey.java +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.exception.NotSupportException; -import org.apache.hugegraph.schema.builder.SchemaBuilder; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.Propertiable; -import org.apache.hugegraph.type.define.AggregateType; -import org.apache.hugegraph.type.define.Cardinality; -import org.apache.hugegraph.type.define.DataType; -import org.apache.hugegraph.type.define.SchemaStatus; -import org.apache.hugegraph.type.define.WriteType; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.LongEncoding; - -public class PropertyKey extends SchemaElement implements Propertiable { - - private DataType dataType; - private Cardinality cardinality; - private AggregateType aggregateType; - private WriteType writeType; - - public PropertyKey(final HugeGraph graph, Id id, String name) { - super(graph, id, name); - this.dataType = DataType.TEXT; - this.cardinality = Cardinality.SINGLE; - this.aggregateType = AggregateType.NONE; - this.writeType = WriteType.OLTP; - } - - @Override - public HugeType type() { - return HugeType.PROPERTY_KEY; - } - - public DataType dataType() { - return this.dataType; - } - - public void dataType(DataType dataType) { - this.dataType = dataType; - } - - public Cardinality cardinality() { - return this.cardinality; - } - - public void cardinality(Cardinality cardinality) { - this.cardinality = cardinality; - } - - public AggregateType aggregateType() { - return this.aggregateType; - } - - public void aggregateType(AggregateType aggregateType) { - this.aggregateType = aggregateType; - } - - public void writeType(WriteType writeType) { - this.writeType = writeType; - } - - public WriteType writeType() { - return this.writeType; - } - - public boolean oltp() { - return this.writeType.oltp(); - } - - public boolean olap() { - return this.writeType.olap(); - } - - @Override - public Set properties() { - return Collections.emptySet(); - } - - public PropertyKey properties(Id... properties) { - if (properties.length > 0) { - throw new NotSupportException("PropertyKey.properties(Id)"); - } - return this; - } - - public void defineDefaultValue(Object value) { - // TODO add a field default_value - this.userdata().put(Userdata.DEFAULT_VALUE, value); - } - - public Object defaultValue() { - // TODO add a field default_value - Object value = this.userdata().get(Userdata.DEFAULT_VALUE); - if (value == null) { - return null; - } - - // Userdata is reloaded from JSON as a raw Map, so a typed default - // value (e.g. Date) comes back as a String. Normalize it to the - // runtime type expected by this property key's data type. Idempotent - // for values already of the expected type. - Object raw = value; - if (this.cardinality == Cardinality.SET && value instanceof Collection && - !(value instanceof Set)) { - raw = new LinkedHashSet<>((Collection) value); - } - - return this.validValueOrThrow(raw); - } - - public boolean hasSameContent(PropertyKey other) { - return super.hasSameContent(other) && - this.dataType == other.dataType() && - this.cardinality == other.cardinality() && - this.aggregateType == other.aggregateType() && - this.writeType == other.writeType(); - } - - public String clazz() { - String dataType = this.dataType().clazz().getSimpleName(); - switch (this.cardinality) { - case SINGLE: - return dataType; - // A set of values: Set - case SET: - return String.format("Set<%s>", dataType); - // A list of values: List - case LIST: - return String.format("List<%s>", dataType); - default: - throw new AssertionError(String.format( - "Unsupported cardinality: '%s'", this.cardinality)); - } - } - - public Class implementClazz() { - Class cls; - switch (this.cardinality) { - case SINGLE: - cls = this.dataType().clazz(); - break; - // A set of values: Set - case SET: - cls = LinkedHashSet.class; - break; - // A list of values: List - case LIST: - cls = ArrayList.class; - break; - default: - throw new AssertionError(String.format( - "Unsupported cardinality: '%s'", this.cardinality)); - } - return cls; - } - - @SuppressWarnings("unchecked") - public T newValue() { - switch (this.cardinality) { - case SET: - return (T) new LinkedHashSet<>(); - case LIST: - return (T) new ArrayList<>(); - default: - // pass - break; - } - - try { - return (T) this.implementClazz().newInstance(); - } catch (Exception e) { - throw new HugeException("Failed to new instance of %s: %s", - this.implementClazz(), e.toString()); - } - } - - /** - * Check property value valid - * - * @param value the property value to be checked data type and cardinality - * @param the property value class - * @return true if data type and cardinality satisfy requirements, - * otherwise false - */ - public boolean checkValueType(V value) { - boolean valid; - - switch (this.cardinality) { - case SINGLE: - valid = this.checkDataType(value); - break; - case SET: - valid = value instanceof Set; - valid = valid && this.checkDataType((Set) value); - break; - case LIST: - valid = value instanceof List; - valid = valid && this.checkDataType((List) value); - break; - default: - throw new AssertionError(String.format( - "Unsupported cardinality: '%s'", this.cardinality)); - } - return valid; - } - - /** - * Check type of the value valid - * - * @param value the property value to be checked data type - * @param the property value original data type - * @return true if the value is or can convert to the data type, - * otherwise false - */ - private boolean checkDataType(V value) { - return this.dataType().clazz().isInstance(value); - } - - /** - * Check type of all the values(maybe some list properties) valid - * - * @param values the property values to be checked data type - * @param the property value class - * @return true if all the values are or can convert to the data type, - * otherwise false - */ - private boolean checkDataType(Collection values) { - boolean valid = true; - for (Object o : values) { - if (!this.checkDataType(o)) { - valid = false; - break; - } - } - return valid; - } - - public Object serialValue(V value, boolean encodeNumber) { - V validValue = this.validValue(value); - E.checkArgument(validValue != null, - "Invalid property value '%s' for key '%s'", - value, this.name()); - E.checkArgument(this.cardinality.single(), - "The cardinality can't be '%s' for navigation key '%s'", - this.cardinality, this.name()); - if (this.dataType.isNumber() || this.dataType.isDate()) { - if (encodeNumber) { - return LongEncoding.encodeNumber(validValue); - } else { - return validValue.toString(); - } - } - return validValue; - } - - public V validValueOrThrow(V value) { - V validValue = this.validValue(value); - if (validValue == null) { - E.checkArgument(false, - "Invalid property value '%s' for key '%s', " + - "expect a value of type %s, actual type %s", - value, this.name(), this.clazz(), - value.getClass().getSimpleName()); - } - return validValue; - } - - public V validValue(V value) { - try { - return this.convValue(value); - } catch (RuntimeException e) { - throw new IllegalArgumentException(String.format( - "Invalid property value '%s' for key '%s': %s", - value, this.name(), e.getMessage())); - } - } - - @SuppressWarnings("unchecked") - private V convValue(V value) { - if (value == null) { - return null; - } - if (this.checkValueType(value)) { - // Same as expected type, no conversion required - return value; - } - - V validValue = null; - Collection validValues; - if (this.cardinality.single()) { - validValue = this.convSingleValue(value); - } else if (value instanceof Collection) { - assert this.cardinality.multiple(); - Collection collection = (Collection) value; - if (value instanceof Set) { - validValues = new LinkedHashSet<>(collection.size()); - } else { - assert value instanceof List; - validValues = new ArrayList<>(collection.size()); - } - for (T element : collection) { - element = this.convSingleValue(element); - if (element == null) { - validValues = null; - break; - } - validValues.add(element); - } - validValue = (V) validValues; - } else { - assert this.cardinality.multiple(); - E.checkArgument(false, - "Property value must be %s, but got '%s'(%s)", - this.cardinality, value, - value.getClass().getSimpleName()); - } - return validValue; - } - - private V convSingleValue(V value) { - if (value == null) { - return null; - } - if (this.dataType().isNumber()) { - @SuppressWarnings("unchecked") - V number = (V) this.dataType().valueToNumber(value); - return number; - } else if (this.dataType().isDate()) { - @SuppressWarnings("unchecked") - V date = (V) this.dataType().valueToDate(value); - return date; - } else if (this.dataType().isUUID()) { - @SuppressWarnings("unchecked") - V uuid = (V) this.dataType().valueToUUID(value); - return uuid; - } else if (this.dataType().isBlob()) { - @SuppressWarnings("unchecked") - V blob = (V) this.dataType().valueToBlob(value); - return blob; - } - - if (this.checkDataType(value)) { - return value; - } - return null; - } - - public interface Builder extends SchemaBuilder { - - TaskWithSchema createWithTask(); - - Builder asText(); - - Builder asInt(); - - Builder asDate(); - - Builder asUUID(); - - Builder asBoolean(); - - Builder asByte(); - - Builder asBlob(); - - Builder asDouble(); - - Builder asFloat(); - - Builder asLong(); - - Builder valueSingle(); - - Builder valueList(); - - Builder valueSet(); - - Builder calcMax(); - - Builder calcMin(); - - Builder calcSum(); - - Builder calcOld(); - - Builder calcSet(); - - Builder calcList(); - - Builder writeType(WriteType writeType); - - Builder cardinality(Cardinality cardinality); - - Builder dataType(DataType dataType); - - Builder aggregateType(AggregateType aggregateType); - - Builder userdata(String key, Object value); - - Builder userdata(Map userdata); - } - - @Override - public Map asMap() { - Map map = new HashMap<>(); - - if (this.dataType != null) { - map.put(P.DATA_TYPE, this.dataType.string()); - } - - if (this.cardinality != null) { - map.put(P.CARDINALITY, this.cardinality.string()); - } - - if (this.aggregateType != null) { - map.put(P.AGGREGATE_TYPE, this.aggregateType.string()); - } - - if (this.writeType != null) { - map.put(P.WRITE_TYPE, this.writeType.string()); - } - - return super.asMap(map); - } - - @SuppressWarnings("unchecked") - public static PropertyKey fromMap(Map map, HugeGraph graph) { - Id id = IdGenerator.of((int) map.get(P.ID)); - String name = (String) map.get(P.NAME); - - PropertyKey propertyKey = new PropertyKey(graph, id, name); - for (Map.Entry entry : map.entrySet()) { - switch (entry.getKey()) { - case P.ID: - case P.NAME: - break; - case P.STATUS: - propertyKey.status( - SchemaStatus.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.USERDATA: - propertyKey.userdata(new Userdata((Map) entry.getValue())); - break; - case P.AGGREGATE_TYPE: - propertyKey.aggregateType( - AggregateType.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.WRITE_TYPE: - propertyKey.writeType( - WriteType.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.DATA_TYPE: - propertyKey.dataType( - DataType.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.CARDINALITY: - propertyKey.cardinality( - Cardinality.valueOf(((String) entry.getValue()).toUpperCase())); - break; - default: - throw new AssertionError(String.format( - "Invalid key '%s' for property key", - entry.getKey())); - } - } - return propertyKey; - } - - public static final class P { - - public static final String ID = "id"; - public static final String NAME = "name"; - - public static final String STATUS = "status"; - public static final String USERDATA = "userdata"; - - public static final String DATA_TYPE = "data_type"; - public static final String CARDINALITY = "cardinality"; - - public static final String AGGREGATE_TYPE = "aggregate_type"; - public static final String WRITE_TYPE = "write_type"; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaElement.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaElement.java deleted file mode 100644 index c36eeaf632..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaElement.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.Collections; -import java.util.Map; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.type.Nameable; -import org.apache.hugegraph.type.Typeable; -import org.apache.hugegraph.type.define.SchemaStatus; -import org.apache.hugegraph.util.E; -import org.apache.tinkerpop.gremlin.structure.Graph; - -import com.google.common.base.Objects; - -public abstract class SchemaElement implements Nameable, Typeable, - Cloneable { - - public static final int MAX_PRIMITIVE_SYS_ID = 32; - public static final int NEXT_PRIMITIVE_SYS_ID = 8; - - // ABS of system schema id must be below MAX_PRIMITIVE_SYS_ID - protected static final int VL_IL_ID = -1; - protected static final int EL_IL_ID = -2; - protected static final int PKN_IL_ID = -3; - protected static final int VLN_IL_ID = -4; - protected static final int ELN_IL_ID = -5; - protected static final int ILN_IL_ID = -6; - protected static final int OLAP_VL_ID = -7; - - // OLAP_ID means all of vertex label ids - public static final Id OLAP_ID = IdGenerator.of(-7); - // OLAP means all of vertex label names - public static final String OLAP = "~olap"; - - public static final Id NONE_ID = IdGenerator.ZERO; - - public static final String UNDEF = "~undefined"; - - protected final HugeGraph graph; - - private final Id id; - private final String name; - private final Userdata userdata; - private SchemaStatus status; - - public SchemaElement(final HugeGraph graph, Id id, String name) { - E.checkArgumentNotNull(id, "SchemaElement id can't be null"); - E.checkArgumentNotNull(name, "SchemaElement name can't be null"); - this.graph = graph; - this.id = id; - this.name = name; - this.userdata = new Userdata(); - this.status = SchemaStatus.CREATED; - } - - public HugeGraph graph() { - E.checkState(this.graph != null, - "Graph is null of schema '%s'", this.name); - return this.graph; - } - - public Id id() { - return this.id; - } - - public long longId() { - return this.id.asLong(); - } - - @Override - public String name() { - return this.name; - } - - public Map userdata() { - return Collections.unmodifiableMap(this.userdata); - } - - /** - * Add userdata. String values of {@link Userdata#CREATE_TIME} are - * normalized to {@link java.util.Date} and malformed strings are rejected. - */ - public void userdata(String key, Object value) { - E.checkArgumentNotNull(key, "userdata key"); - E.checkArgumentNotNull(value, "userdata value"); - this.userdata.put(key, value); - } - - /** - * Add userdata in bulk. String values of {@link Userdata#CREATE_TIME} are - * normalized to {@link java.util.Date} and malformed strings are rejected. - */ - public void userdata(Userdata userdata) { - E.checkArgumentNotNull(userdata, "userdata"); - this.userdata.putAll(userdata); - } - - public void removeUserdata(String key) { - E.checkArgumentNotNull(key, "The userdata key can't be null"); - this.userdata.remove(key); - } - - public void removeUserdata(Userdata userdata) { - E.checkArgumentNotNull(userdata, "userdata"); - for (String key : userdata.keySet()) { - this.userdata.remove(key); - } - } - - public SchemaStatus status() { - return this.status; - } - - public void status(SchemaStatus status) { - this.status = status; - } - - public boolean system() { - return this.longId() < 0L; - } - - public boolean primitive() { - long id = this.longId(); - return -MAX_PRIMITIVE_SYS_ID <= id && id < 0L; - } - - public boolean hidden() { - return Graph.Hidden.isHidden(this.name()); - } - - public SchemaElement copy() { - try { - return (SchemaElement) super.clone(); - } catch (CloneNotSupportedException e) { - throw new HugeException("Failed to clone schema", e); - } - } - - public boolean hasSameContent(SchemaElement other) { - return Objects.equal(this.name(), other.name()) && - Objects.equal(this.userdata(), other.userdata()); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof SchemaElement)) { - return false; - } - - SchemaElement other = (SchemaElement) obj; - return this.type() == other.type() && this.id.equals(other.id()); - } - - @Override - public int hashCode() { - return this.type().hashCode() ^ this.id.hashCode(); - } - - @Override - public String toString() { - return String.format("%s(id=%s)", this.name, this.id); - } - - public static int schemaId(Id id) { - long l = id.asLong(); - // Currently we limit the schema id to within 4 bytes - E.checkArgument(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE, - "Schema id is out of bound: %s", l); - return (int) l; - } - - public static class TaskWithSchema { - - private SchemaElement schemaElement; - private Id task; - - public TaskWithSchema(SchemaElement schemaElement, Id task) { - E.checkNotNull(schemaElement, "schema element"); - this.schemaElement = schemaElement; - this.task = task; - } - - public void propertyKey(PropertyKey propertyKey) { - E.checkNotNull(propertyKey, "property key"); - this.schemaElement = propertyKey; - } - - public void indexLabel(IndexLabel indexLabel) { - E.checkNotNull(indexLabel, "index label"); - this.schemaElement = indexLabel; - } - - public PropertyKey propertyKey() { - E.checkState(this.schemaElement instanceof PropertyKey, - "Expect property key, but actual schema type is " + - "'%s'", this.schemaElement.getClass()); - return (PropertyKey) this.schemaElement; - } - - public IndexLabel indexLabel() { - E.checkState(this.schemaElement instanceof IndexLabel, - "Expect index label, but actual schema type is " + - "'%s'", this.schemaElement.getClass()); - return (IndexLabel) this.schemaElement; - } - - public SchemaElement schemaElement() { - return this.schemaElement; - } - - public Id task() { - return this.task; - } - } - - public abstract Map asMap(); - - public Map asMap(Map map) { - E.checkState(this.id != null, - "Property key id can't be null"); - E.checkState(this.name != null, - "Property key name can't be null"); - E.checkState(this.status != null, - "Property status can't be null"); - - map.put(P.ID, this.id); - map.put(P.NAME, this.name); - map.put(P.STATUS, this.status.string()); - map.put(P.USERDATA, this.userdata); - - return map; - } - - public static final class P { - - public static final String ID = "id"; - public static final String NAME = "name"; - - public static final String STATUS = "status"; - public static final String USERDATA = "userdata"; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaLabel.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaLabel.java deleted file mode 100644 index 09de43e2d8..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaLabel.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.Indexable; -import org.apache.hugegraph.type.Propertiable; -import org.apache.hugegraph.util.E; - -import com.google.common.base.Objects; - -public abstract class SchemaLabel extends SchemaElement - implements Indexable, Propertiable { - - private final Set properties; - private final Set nullableKeys; - private final Set indexLabels; - private boolean enableLabelIndex; - private long ttl; - private Id ttlStartTime; - - public SchemaLabel(final HugeGraph graph, Id id, String name) { - super(graph, id, name); - this.properties = new HashSet<>(); - this.nullableKeys = new HashSet<>(); - this.indexLabels = new HashSet<>(); - this.enableLabelIndex = true; - this.ttl = 0L; - this.ttlStartTime = NONE_ID; - } - - @Override - public Set properties() { - return Collections.unmodifiableSet(this.properties); - } - - public void properties(Set properties) { - this.properties.addAll(properties); - } - - public SchemaLabel properties(Id... ids) { - this.properties.addAll(Arrays.asList(ids)); - return this; - } - - public void property(Id id) { - this.properties.add(id); - } - - public Set nullableKeys() { - return Collections.unmodifiableSet(this.nullableKeys); - } - - public void nullableKey(Id id) { - this.nullableKeys.add(id); - } - - public void nullableKeys(Id... ids) { - this.nullableKeys.addAll(Arrays.asList(ids)); - } - - public void nullableKeys(Set nullableKeys) { - this.nullableKeys.addAll(nullableKeys); - } - - @Override - public Set indexLabels() { - return Collections.unmodifiableSet(this.indexLabels); - } - - public void addIndexLabel(Id id) { - this.indexLabels.add(id); - } - - public void addIndexLabels(Id... ids) { - this.indexLabels.addAll(Arrays.asList(ids)); - } - - public boolean existsIndexLabel() { - return !this.indexLabels().isEmpty(); - } - - public void removeIndexLabel(Id id) { - this.indexLabels.remove(id); - } - - public boolean enableLabelIndex() { - return this.enableLabelIndex; - } - - public void enableLabelIndex(boolean enable) { - this.enableLabelIndex = enable; - } - - public boolean undefined() { - return this.name() == UNDEF; - } - - public void ttl(long ttl) { - assert ttl >= 0L; - this.ttl = ttl; - } - - public long ttl() { - assert this.ttl >= 0L; - return this.ttl; - } - - public void ttlStartTime(Id id) { - this.ttlStartTime = id; - } - - public Id ttlStartTime() { - return this.ttlStartTime; - } - - public String ttlStartTimeName() { - return NONE_ID.equals(this.ttlStartTime) ? null : - this.graph.propertyKey(this.ttlStartTime).name(); - } - - public boolean hasSameContent(SchemaLabel other) { - return super.hasSameContent(other) && this.ttl == other.ttl && - this.enableLabelIndex == other.enableLabelIndex && - Objects.equal(this.graph.mapPkId2Name(this.properties), - other.graph.mapPkId2Name(other.properties)) && - Objects.equal(this.graph.mapPkId2Name(this.nullableKeys), - other.graph.mapPkId2Name(other.nullableKeys)) && - Objects.equal(this.graph.mapIlId2Name(this.indexLabels), - other.graph.mapIlId2Name(other.indexLabels)) && - Objects.equal(this.ttlStartTimeName(), other.ttlStartTimeName()); - } - - public static Id getLabelId(HugeGraph graph, HugeType type, Object label) { - E.checkNotNull(graph, "graph"); - E.checkNotNull(type, "type"); - E.checkNotNull(label, "label"); - if (label instanceof Number) { - return IdGenerator.of(((Number) label).longValue()); - } else if (label instanceof String) { - if (type.isVertex()) { - return graph.vertexLabel((String) label).id(); - } else if (type.isEdge()) { - return graph.edgeLabel((String) label).id(); - } else { - throw new HugeException( - "Not support query from '%s' with label '%s'", - type, label); - } - } else { - throw new HugeException( - "The label type must be number or string, but got '%s'", - label.getClass()); - } - } - - public static Id getVertexLabelId(HugeGraph graph, Object label) { - return SchemaLabel.getLabelId(graph, HugeType.VERTEX, label); - } - - public static Id getEdgeLabelId(HugeGraph graph, Object label) { - return SchemaLabel.getLabelId(graph, HugeType.EDGE, label); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaManager.java index 7ea46b0d7b..0663f194d9 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/SchemaManager.java @@ -27,6 +27,11 @@ import org.apache.hugegraph.schema.builder.IndexLabelBuilder; import org.apache.hugegraph.schema.builder.PropertyKeyBuilder; import org.apache.hugegraph.schema.builder.VertexLabelBuilder; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Graph; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/Userdata.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/Userdata.java deleted file mode 100644 index 9d2b9dbd19..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/Userdata.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.hugegraph.exception.NotAllowException; -import org.apache.hugegraph.type.define.Action; -import org.apache.hugegraph.util.DateUtil; - -public class Userdata extends HashMap { - - private static final long serialVersionUID = -1235451175617197049L; - - public static final String CREATE_TIME = "~create_time"; - public static final String DEFAULT_VALUE = "~default_value"; - - public Userdata() { - } - - public Userdata(Map map) { - this.putAll(map); - } - - /** - * Normalizes the value before storing so the {@link #CREATE_TIME}-is-Date - * invariant holds regardless of how entries are added. - */ - @Override - public Object put(String key, Object value) { - return super.put(key, normalizeValue(key, value)); - } - - @Override - public void putAll(Map map) { - for (Map.Entry e : map.entrySet()) { - this.put(e.getKey(), e.getValue()); - } - } - - /** - * Normalize internal userdata values whose runtime type can diverge from - * their serialized form. The only such key today is {@link #CREATE_TIME}: - * it is written as a {@link java.util.Date} but persisted as a formatted - * JSON string by the backend serializers, and Jackson cannot re-type a - * value to {@code Date} when the target is a raw {@code Map}. This method - * restores the original type after deserialization. Idempotent for values - * already of the expected type. - *

- * An empty string is passed through unchanged: it is the key-only - * placeholder used by the {@code eliminate()}/{@code DELETE} builder flow - * (e.g. {@code .userdata(CREATE_TIME, "").eliminate()}), where the value is - * ignored and only the key drives {@code removeUserdata}. Parsing it would - * fail before the eliminate path can apply its key-only semantics. - */ - public static Object normalizeValue(String key, Object value) { - if (CREATE_TIME.equals(key) && value instanceof String && - !((String) value).isEmpty()) { - try { - return DateUtil.parse((String) value); - } catch (RuntimeException e) { - throw new IllegalArgumentException(String.format( - "Invalid userdata '%s' value: '%s'", - CREATE_TIME, value), e); - } - } - return value; - } - - public static void check(Userdata userdata, Action action) { - if (userdata == null) { - return; - } - switch (action) { - case INSERT: - case APPEND: - for (Map.Entry e : userdata.entrySet()) { - if (e.getValue() == null) { - throw new NotAllowException( - "Not allowed to pass null userdata value " + - "when create or append schema"); - } - } - break; - case ELIMINATE: - case DELETE: - // pass - break; - default: - throw new AssertionError(String.format( - "Unknown schema action '%s'", action)); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/VertexLabel.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/VertexLabel.java deleted file mode 100644 index 3f62df8631..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/VertexLabel.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.builder.SchemaBuilder; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.IdStrategy; -import org.apache.hugegraph.type.define.SchemaStatus; - -import com.google.common.base.Objects; - -public class VertexLabel extends SchemaLabel { - - public static final VertexLabel NONE = new VertexLabel(null, NONE_ID, UNDEF); - - // OLAP_VL_ID means all of vertex label ids - private static final Id OLAP_VL_ID = IdGenerator.of(SchemaLabel.OLAP_VL_ID); - // OLAP_VL_NAME means all of vertex label names - private static final String OLAP_VL_NAME = "*olap"; - // OLAP_VL means all of vertex labels - public static final VertexLabel OLAP_VL = new VertexLabel(null, OLAP_VL_ID, - OLAP_VL_NAME); - - private IdStrategy idStrategy; - private List primaryKeys; - - public VertexLabel(final HugeGraph graph, Id id, String name) { - super(graph, id, name); - this.idStrategy = IdStrategy.DEFAULT; - this.primaryKeys = new ArrayList<>(); - } - - @Override - public HugeType type() { - return HugeType.VERTEX_LABEL; - } - - public boolean olap() { - return VertexLabel.OLAP_VL.id().equals(this.id()); - } - - public IdStrategy idStrategy() { - return this.idStrategy; - } - - public void idStrategy(IdStrategy idStrategy) { - this.idStrategy = idStrategy; - } - - public List primaryKeys() { - return Collections.unmodifiableList(this.primaryKeys); - } - - public void primaryKey(Id id) { - this.primaryKeys.add(id); - } - - public void primaryKeys(Id... ids) { - this.primaryKeys.addAll(Arrays.asList(ids)); - } - - public boolean existsLinkLabel() { - return this.graph().existsLinkLabel(this.id()); - } - - public boolean hasSameContent(VertexLabel other) { - return super.hasSameContent(other) && - this.idStrategy == other.idStrategy && - Objects.equal(this.graph.mapPkId2Name(this.primaryKeys), - other.graph.mapPkId2Name(other.primaryKeys)); - } - - public static VertexLabel undefined(HugeGraph graph) { - return new VertexLabel(graph, NONE_ID, UNDEF); - } - - public static VertexLabel undefined(HugeGraph graph, Id id) { - return new VertexLabel(graph, id, UNDEF); - } - - public interface Builder extends SchemaBuilder { - - Id rebuildIndex(); - - Builder idStrategy(IdStrategy idStrategy); - - Builder useAutomaticId(); - - Builder usePrimaryKeyId(); - - Builder useCustomizeStringId(); - - Builder useCustomizeNumberId(); - - Builder useCustomizeUuidId(); - - Builder properties(String... properties); - - Builder primaryKeys(String... keys); - - Builder nullableKeys(String... keys); - - Builder ttl(long ttl); - - Builder ttlStartTime(String ttlStartTime); - - Builder enableLabelIndex(boolean enable); - - Builder userdata(String key, Object value); - - Builder userdata(Map userdata); - } - - @Override - public Map asMap() { - HashMap map = new HashMap(); - - map.put(P.PROPERTIES, this.properties()); - - map.put(P.NULLABLE_KEYS, this.nullableKeys()); - - map.put(P.INDEX_LABELS, this.indexLabels()); - - map.put(P.ENABLE_LABEL_INDEX, this.enableLabelIndex()); - - map.put(P.TTL, String.valueOf(this.ttl())); - - map.put(P.TT_START_TIME, this.ttlStartTime().asString()); - - map.put(P.ID_STRATEGY, this.idStrategy().string()); - - map.put(P.PRIMARY_KEYS, this.primaryKeys()); - - return super.asMap(map); - } - - @SuppressWarnings("unchecked") - public static VertexLabel fromMap(Map map, HugeGraph graph) { - Id id = IdGenerator.of((int) map.get(VertexLabel.P.ID)); - String name = (String) map.get(VertexLabel.P.NAME); - - VertexLabel vertexLabel = new VertexLabel(graph, id, name); - for (Map.Entry entry : map.entrySet()) { - switch (entry.getKey()) { - case P.ID: - case P.NAME: - break; - case P.STATUS: - vertexLabel.status( - SchemaStatus.valueOf(((String) entry.getValue()).toUpperCase())); - break; - case P.USERDATA: - vertexLabel.userdata(new Userdata((Map) entry.getValue())); - break; - case P.PROPERTIES: - Set ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - vertexLabel.properties(ids); - break; - case P.NULLABLE_KEYS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - vertexLabel.nullableKeys(ids); - break; - case P.INDEX_LABELS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - vertexLabel.addIndexLabels(ids.toArray(new Id[0])); - break; - case P.ENABLE_LABEL_INDEX: - boolean enableLabelIndex = (Boolean) entry.getValue(); - vertexLabel.enableLabelIndex(enableLabelIndex); - break; - case P.TTL: - long ttl = Long.parseLong((String) entry.getValue()); - vertexLabel.ttl(ttl); - break; - case P.TT_START_TIME: - long ttlStartTime = - Long.parseLong((String) entry.getValue()); - vertexLabel.ttlStartTime(IdGenerator.of(ttlStartTime)); - break; - case P.ID_STRATEGY: - IdStrategy idStrategy = - IdStrategy.valueOf(((String) entry.getValue()).toUpperCase()); - vertexLabel.idStrategy(idStrategy); - break; - case P.PRIMARY_KEYS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - vertexLabel.primaryKeys(ids.toArray(new Id[0])); - break; - default: - throw new AssertionError(String.format( - "Invalid key '%s' for vertex label", - entry.getKey())); - } - } - return vertexLabel; - } - - public static final class P { - - public static final String ID = "id"; - public static final String NAME = "name"; - - public static final String STATUS = "status"; - public static final String USERDATA = "userdata"; - - public static final String PROPERTIES = "properties"; - public static final String NULLABLE_KEYS = "nullableKeys"; - public static final String INDEX_LABELS = "indexLabels"; - - public static final String ENABLE_LABEL_INDEX = "enableLabelIndex"; - public static final String TTL = "ttl"; - public static final String TT_START_TIME = "ttlStartTime"; - public static final String ID_STRATEGY = "idStrategy"; - public static final String PRIMARY_KEYS = "primaryKeys"; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/AbstractBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/AbstractBuilder.java index 0e0e95256c..2baaf8130b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/AbstractBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/AbstractBuilder.java @@ -21,15 +21,15 @@ import java.util.function.Function; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.backend.tx.ISchemaTransaction; import org.apache.hugegraph.exception.ExistedException; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.GraphMode; import org.apache.hugegraph.type.define.SchemaStatus; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java index 32937a2cf0..e46d4c2f2a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java @@ -28,16 +28,17 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.backend.tx.ISchemaTransaction; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Action; import org.apache.hugegraph.type.define.EdgeLabelType; @@ -91,7 +92,7 @@ public EdgeLabelBuilder(ISchemaTransaction transaction, HugeGraph graph, EdgeLabel copy) { super(transaction, graph); E.checkNotNull(copy, "copy"); - HugeGraph origin = copy.graph(); + HugeGraphSupplier origin = copy.graph(); this.id = null; this.name = copy.name(); this.links = mapPairId2Name(origin, copy.links()); @@ -206,7 +207,6 @@ public EdgeLabel create() { this.checkNullableKeys(Action.INSERT); Userdata.check(this.userdata, Action.INSERT); this.checkTTL(); - this.checkUserdata(Action.INSERT); edgeLabel = this.build(); assert edgeLabel.name().equals(name); @@ -731,42 +731,26 @@ private void checkTTL() { "but got '%s(%s)'", this.ttlStartTime, pkey.dataType()); } - private void checkUserdata(Action action) { - switch (action) { - case INSERT: - case APPEND: - for (Map.Entry e : this.userdata.entrySet()) { - if (e.getValue() == null) { - throw new NotAllowException( - "Not allowed pass null userdata value when " + - "create or append edge label"); - } - } - break; - case ELIMINATE: - case DELETE: - // pass - break; - default: - throw new AssertionError(String.format( - "Unknown schema action '%s'", action)); - } - } - private static Set mapPkId2Name(HugeGraph graph, Set ids) { + private static Set mapPkId2Name(HugeGraphSupplier graph, Set ids) { return new HashSet<>(graph.mapPkId2Name(ids)); } - private static List mapPkId2Name(HugeGraph graph, List ids) { + private static List mapPkId2Name(HugeGraphSupplier graph, List ids) { return graph.mapPkId2Name(ids); } - private static String mapElId2Name(HugeGraph graph, Id fatherId) { - return graph.mapElId2Name(ImmutableList.of(fatherId)).get(0); + private static String mapElId2Name(HugeGraphSupplier graph, Id fatherId) { + return graph.edgeLabel(fatherId).name(); } - private static Set> mapPairId2Name(HugeGraph graph, + private static Set> mapPairId2Name(HugeGraphSupplier graph, Set> pairs) { - return graph.mapPairId2Name(pairs); + Set> names = new HashSet<>(); + for (Pair pair : pairs) { + names.add(Pair.of(graph.vertexLabel(pair.getLeft()).name(), + graph.vertexLabel(pair.getRight()).name())); + } + return names; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/IndexLabelBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/IndexLabelBuilder.java index 397df66229..abb4ca8fbd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/IndexLabelBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/IndexLabelBuilder.java @@ -25,21 +25,21 @@ import java.util.concurrent.TimeoutException; import java.util.function.BiPredicate; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.backend.tx.ISchemaTransaction; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Action; import org.apache.hugegraph.type.define.CollectionType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/PropertyKeyBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/PropertyKeyBuilder.java index a50b426d1d..d971fd5aeb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/PropertyKeyBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/PropertyKeyBuilder.java @@ -20,19 +20,19 @@ import java.util.Map; import java.util.concurrent.TimeoutException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.backend.tx.ISchemaTransaction; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.exception.NotSupportException; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Action; import org.apache.hugegraph.type.define.AggregateType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/SchemaBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/SchemaBuilder.java deleted file mode 100644 index 28ef0c15f5..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/SchemaBuilder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.schema.builder; - -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.SchemaElement; - -public interface SchemaBuilder { - - SchemaBuilder id(long id); - - T build(); - - T create(); - - T append(); - - T eliminate(); - - Id remove(); - - SchemaBuilder ifNotExist(); - - SchemaBuilder checkExist(boolean checkExist); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java index 4962646209..95b14b2697 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java @@ -27,15 +27,16 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.backend.tx.ISchemaTransaction; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Action; import org.apache.hugegraph.type.define.IdStrategy; @@ -79,7 +80,7 @@ public VertexLabelBuilder(ISchemaTransaction transaction, HugeGraph graph, VertexLabel copy) { super(transaction, graph); E.checkNotNull(copy, "copy"); - HugeGraph origin = copy.graph(); + HugeGraphSupplier origin = copy.graph(); this.id = null; this.name = copy.name(); this.idStrategy = copy.idStrategy(); @@ -138,7 +139,6 @@ public VertexLabel create() { this.checkNullableKeys(Action.INSERT); Userdata.check(this.userdata, Action.INSERT); this.checkTTL(); - this.checkUserdata(Action.INSERT); vertexLabel = this.build(); assert vertexLabel.name().equals(name); @@ -586,32 +586,12 @@ private void checkTTL() { "but got '%s(%s)'", this.ttlStartTime, pkey.dataType()); } - private void checkUserdata(Action action) { - switch (action) { - case INSERT: - case APPEND: - for (Map.Entry e : this.userdata.entrySet()) { - if (e.getValue() == null) { - throw new NotAllowException( - "Not allowed pass null userdata value when " + - "create or append edge label"); - } - } - break; - case ELIMINATE: - case DELETE: - // pass - break; - default: - throw new AssertionError(String.format("Unknown schema action '%s'", action)); - } - } - private static Set mapPkId2Name(HugeGraph graph, Set ids) { + private static Set mapPkId2Name(HugeGraphSupplier graph, Set ids) { return new HashSet<>(graph.mapPkId2Name(ids)); } - private static List mapPkId2Name(HugeGraph graph, List ids) { + private static List mapPkId2Name(HugeGraphSupplier graph, List ids) { return graph.mapPkId2Name(ids); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java index f821809b63..d78415c691 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/space/GraphSpace.java @@ -24,7 +24,7 @@ import java.util.Map; import org.apache.commons.lang.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.util.E; public class GraphSpace { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/GraphType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/GraphType.java deleted file mode 100644 index 7cf5ee3b4d..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/GraphType.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.structure; - -import org.apache.hugegraph.type.Nameable; -import org.apache.hugegraph.type.Typeable; - -public interface GraphType extends Nameable, Typeable { - -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java index 5bf7011a6f..9ba85a9baa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java @@ -22,24 +22,21 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; -import org.apache.hugegraph.backend.serializer.BytesBuffer; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.E; -import org.apache.logging.log4j.util.Strings; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Property; @@ -47,17 +44,14 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyProperty; -import com.google.common.collect.ImmutableList; public class HugeEdge extends HugeElement implements Edge, Cloneable { - private Id id; - private final EdgeLabel label; - private String name; + private BaseEdge element; private HugeVertex sourceVertex; private HugeVertex targetVertex; - private boolean isOutEdge; + public HugeEdge(HugeVertex owner, Id id, EdgeLabel label, HugeVertex other) { @@ -70,52 +64,69 @@ public HugeEdge(final HugeGraph graph, Id id, EdgeLabel label) { super(graph); E.checkArgumentNotNull(label, "Edge label can't be null"); - this.label = label; - - this.id = id; - this.name = null; + this.element = new BaseEdge(id, label); + this.element.isOutEdge(true); this.sourceVertex = null; this.targetVertex = null; - this.isOutEdge = true; + } + + /** Adopt decoded shared state and attach engine endpoint wrappers. */ + public HugeEdge(final HugeGraph graph, BaseEdge element) { + this(graph, element, null); + } + + public HugeEdge(final HugeGraph graph, BaseEdge element, HugeVertex owner) { + super(graph); + E.checkArgumentNotNull(element, "Edge element can't be null"); + E.checkArgumentNotNull(element.schemaLabel(), "Edge label can't be null"); + this.element = element; + BaseVertex source = element.sourceVertex(); + BaseVertex target = element.targetVertex(); + this.sourceVertex = this.wrapVertex(graph, source, owner); + this.targetVertex = target == source ? this.sourceVertex : this.wrapVertex(graph, target, owner); + } + + private HugeVertex wrapVertex(HugeGraph graph, BaseVertex vertex, HugeVertex owner) { + if (vertex == null) { + return null; + } + return owner != null && owner.element() == vertex ? owner : new HugeVertex(graph, vertex); + } + + @Override + public BaseEdge element() { + return this.element; } @Override public HugeType type() { // NOTE: we optimize the edge type that let it include direction - return this.isOutEdge ? HugeType.EDGE_OUT : HugeType.EDGE_IN; + return this.element.isOutEdge() ? HugeType.EDGE_OUT : HugeType.EDGE_IN; } @Override public EdgeId id() { - return (EdgeId) this.id; + return (EdgeId) this.element.id(); } @Override public EdgeLabel schemaLabel() { - assert this.graph().sameAs(this.label.graph()); - return this.label; + assert this.graph().sameAs(this.element.schemaLabel().graph()); + return this.element.schemaLabel(); } @Override public String name() { - if (this.name == null) { - List sortValues = this.sortValues(); - if (sortValues.isEmpty()) { - this.name = Strings.EMPTY; - } else { - this.name = ConditionQuery.concatValues(sortValues); - } - } - return this.name; + return this.element.name(); } public void name(String name) { - this.name = name; + this.element.name(name); } @Override public String label() { - return this.label.name(); + return this.element.schemaLabel().name(); } public boolean selfLoop() { @@ -124,7 +135,7 @@ public boolean selfLoop() { } public Directions direction() { - return this.isOutEdge ? Directions.OUT : Directions.IN; + return this.element.isOutEdge() ? Directions.OUT : Directions.IN; } public boolean matchDirection(Directions direction) { @@ -135,60 +146,25 @@ public boolean matchDirection(Directions direction) { } public boolean isDirection(Directions direction) { - return this.isOutEdge && direction == Directions.OUT || - !this.isOutEdge && direction == Directions.IN; + return this.element.isOutEdge() && direction == Directions.OUT || + !this.element.isOutEdge() && direction == Directions.IN; } @Watched(prefix = "edge") public void assignId() { - // Generate an id and assign - if (this.schemaLabel().hasFather()) { - this.id = new EdgeId(this.ownerVertex(), this.direction(), - this.schemaLabel().fatherId(), - this.schemaLabel().id(), - this.name(), - this.otherVertex()); - } else { - this.id = new EdgeId(this.ownerVertex(), this.direction(), - this.schemaLabel().id(), - this.schemaLabel().id(), - this.name(), this.otherVertex()); - } - - if (this.fresh()) { - int len = this.id.length(); - E.checkArgument(len <= BytesBuffer.EID_LEN_MAX, - "The max length of edge id is %s, but got %s {%s}", - BytesBuffer.EID_LEN_MAX, len, this.id); - } + this.element.assignId(); } @Watched(prefix = "edge") public EdgeId idWithDirection() { - return ((EdgeId) this.id).directed(true); + return this.element.idWithDirection(); } @Watched(prefix = "edge") protected List sortValues() { - List sortKeys = this.schemaLabel().sortKeys(); - if (sortKeys.isEmpty()) { - return ImmutableList.of(); - } - List propValues = new ArrayList<>(sortKeys.size()); - for (Id sk : sortKeys) { - HugeProperty property = this.getProperty(sk); - E.checkState(property != null, - "The value of sort key '%s' can't be null", sk); - Object propValue = property.serialValue(true); - if (Strings.EMPTY.equals(propValue)) { - propValue = ConditionQuery.INDEX_VALUE_EMPTY; - } - propValues.add(propValue); - } - return propValues; + return this.element.sortValues(); } - @Watched(prefix = "edge") @Override public void remove() { this.removed(true); @@ -208,7 +184,7 @@ public void remove() { public Property property(String key, V value) { PropertyKey propertyKey = this.graph().propertyKey(key); // Check key in edge label - E.checkArgument(this.label.properties().contains(propertyKey.id()), + E.checkArgument(this.element.schemaLabel().properties().contains(propertyKey.id()), "Invalid property '%s' for edge label '%s'", key, this.label()); if (value == null) { @@ -238,6 +214,11 @@ protected HugeEdgeProperty newProperty(PropertyKey pkey, V val) { return new HugeEdgeProperty<>(this, pkey, val); } + @Override + protected HugeEdgeProperty wrapProperty(BaseProperty property) { + return new HugeEdgeProperty<>(this, property); + } + @Watched(prefix = "edge") @Override protected void onUpdateProperty(Cardinality cardinality, @@ -275,7 +256,7 @@ protected boolean ensureFilledProperties(boolean throwIfNotExist) { if (edge == null && !throwIfNotExist) { return false; } - E.checkState(edge != null, "Edge '%s' does not exist", this.id); + E.checkState(edge != null, "Edge '%s' does not exist", this.element.id()); this.copyProperties((HugeEdge) edge); this.updateToDefaultValueIfNone(); return true; @@ -319,31 +300,7 @@ public Iterator> properties(String... keys) { @Override public Object sysprop(HugeKeys key) { - switch (key) { - case ID: - return this.id(); - case OWNER_VERTEX: - return this.ownerVertex().id(); - case LABEL: - if (this.schemaLabel().hasFather()) { - return this.schemaLabel().fatherId(); - } else { - return this.schemaLabel().id(); - } - case DIRECTION: - return this.direction(); - case SUB_LABEL: - return this.schemaLabel().id(); - case OTHER_VERTEX: - return this.otherVertex().id(); - case SORT_VALUES: - return this.name(); - case PROPERTIES: - return this.getPropertiesMap(); - default: - E.checkArgument(false, "Invalid system property '%s' of Edge", key); - return null; - } + return this.element.sysprop(key); } @Override @@ -380,7 +337,7 @@ public Vertex inVertex() { public void vertices(HugeVertex owner, HugeVertex other) { Id ownerLabel = owner.schemaLabel().id(); Id otherLabel = other.schemaLabel().id(); - for (Pair link : this.label.links()) { + for (Pair link : this.element.schemaLabel().links()) { if (ownerLabel.equals(link.getLeft()) && otherLabel.equals(link.getRight())) { this.vertices(true, owner, other); @@ -392,8 +349,8 @@ public void vertices(HugeVertex owner, HugeVertex other) { } public void vertices(boolean outEdge, HugeVertex owner, HugeVertex other) { - this.isOutEdge = outEdge; - if (this.isOutEdge) { + this.element.vertices(outEdge, owner.element(), other.element()); + if (this.element.isOutEdge()) { this.sourceVertex = owner; this.targetVertex = other; } else { @@ -404,10 +361,7 @@ public void vertices(boolean outEdge, HugeVertex owner, HugeVertex other) { @Watched public HugeEdge switchOwner() { - HugeEdge edge = this.clone(); - edge.isOutEdge = !edge.isOutEdge; - edge.id = ((EdgeId) edge.id).switchDirection(); - return edge; + return this.cloneWithElement(this.element.switchOwner()); } public HugeEdge switchToOutDirection() { @@ -418,7 +372,7 @@ public HugeEdge switchToOutDirection() { } public HugeVertex ownerVertex() { - return this.isOutEdge ? this.sourceVertex() : this.targetVertex(); + return this.element.isOutEdge() ? this.sourceVertex() : this.targetVertex(); } public HugeVertex sourceVertex() { @@ -428,6 +382,7 @@ public HugeVertex sourceVertex() { public void sourceVertex(HugeVertex sourceVertex) { this.sourceVertex = sourceVertex; + this.element.sourceVertex(sourceVertex.element()); } public HugeVertex targetVertex() { @@ -437,6 +392,7 @@ public HugeVertex targetVertex() { public void targetVertex(HugeVertex targetVertex) { this.targetVertex = targetVertex; + this.element.targetVertex(targetVertex.element()); } private void checkAdjacentVertexExist(HugeVertex vertex) { @@ -477,7 +433,7 @@ public HugeVertex otherVertex(HugeVertex vertex) { } public HugeVertex otherVertex() { - return this.isOutEdge ? this.targetVertex() : this.sourceVertex(); + return this.element.isOutEdge() ? this.targetVertex() : this.sourceVertex(); } /** @@ -501,8 +457,14 @@ public HugeEdge copy() { @Override protected HugeEdge clone() { + return this.cloneWithElement(this.element.clone()); + } + + private HugeEdge cloneWithElement(BaseEdge element) { try { - return (HugeEdge) super.clone(); + HugeEdge edge = (HugeEdge) super.clone(); + edge.element = element; + return edge; } catch (CloneNotSupportedException e) { throw new HugeException("Failed to clone HugeEdge", e); } @@ -528,36 +490,21 @@ public static HugeEdge constructEdge(HugeVertex ownerVertex, EdgeLabel edgeLabel, String sortValues, Id otherVertexId) { - HugeGraph graph = ownerVertex.graph(); - VertexLabel srcLabel = graph.vertexLabelOrNone(edgeLabel.sourceLabel()); - VertexLabel tgtLabel = graph.vertexLabelOrNone(edgeLabel.targetLabel()); - - VertexLabel otherVertexLabel; - if (isOutEdge) { - ownerVertex.correctVertexLabel(srcLabel); - otherVertexLabel = tgtLabel; - } else { - ownerVertex.correctVertexLabel(tgtLabel); - otherVertexLabel = srcLabel; - } - HugeVertex otherVertex = new HugeVertex(graph, otherVertexId, otherVertexLabel); - - ownerVertex.propNotLoaded(); - otherVertex.propNotLoaded(); - - HugeEdge edge = new HugeEdge(graph, null, edgeLabel); - edge.name(sortValues); - edge.vertices(isOutEdge, ownerVertex, otherVertex); - edge.assignId(); + BaseEdge element = BaseEdge.createEdge(ownerVertex.graph(), ownerVertex.element(), isOutEdge, + edgeLabel, sortValues, otherVertexId); + return attachEdge(ownerVertex, element); + } - if (isOutEdge) { + private static HugeEdge attachEdge(HugeVertex ownerVertex, BaseEdge element) { + HugeEdge edge = new HugeEdge(ownerVertex.graph(), element, ownerVertex); + HugeVertex otherVertex = edge.otherVertex(); + if (element.isOutEdge()) { ownerVertex.addOutEdge(edge); otherVertex.addInEdge(edge.switchOwner()); } else { ownerVertex.addInEdge(edge); otherVertex.addOutEdge(edge.switchOwner()); } - return edge; } @@ -566,25 +513,11 @@ public static HugeEdge constructEdgeWithoutLabel(HugeVertex ownerVertex, String sortValues, Id otherVertexId) { HugeGraph graph = ownerVertex.graph(); - HugeVertex otherVertex = new HugeVertex(graph, otherVertexId, - VertexLabel.NONE); - ownerVertex.propNotLoaded(); - otherVertex.propNotLoaded(); - - HugeEdge edge = new HugeEdge(graph, null, EdgeLabel.NONE); - edge.name(sortValues); - edge.vertices(isOutEdge, ownerVertex, otherVertex); - edge.assignId(); - - if (isOutEdge) { - ownerVertex.addOutEdge(edge); - otherVertex.addInEdge(edge.switchOwner()); - } else { - ownerVertex.addInEdge(edge); - otherVertex.addOutEdge(edge.switchOwner()); - } - - return edge; + EdgeLabel label = EdgeLabel.undefined(graph, EdgeLabel.NONE.id()); + VertexLabel otherLabel = VertexLabel.undefined(graph); + BaseEdge element = BaseEdge.createEdge(ownerVertex.element(), isOutEdge, label, + sortValues, otherVertexId, otherLabel); + return attachEdge(ownerVertex, element); } public static HugeEdge constructEdgeWithoutGraph(HugeVertex ownerVertex, @@ -592,37 +525,8 @@ public static HugeEdge constructEdgeWithoutGraph(HugeVertex ownerVertex, EdgeLabel edgeLabel, String sortValues, Id otherVertexId) { - Id ownerLabelId = edgeLabel.sourceLabel(); - Id otherLabelId = edgeLabel.targetLabel(); - VertexLabel srcLabel = new VertexLabel(null, ownerLabelId, "UNDEF"); - VertexLabel tgtLabel = new VertexLabel(null, otherLabelId, "UNDEF"); - - VertexLabel otherVertexLabel; - if (isOutEdge) { - ownerVertex.correctVertexLabel(srcLabel); - otherVertexLabel = tgtLabel; - } else { - ownerVertex.correctVertexLabel(tgtLabel); - otherVertexLabel = srcLabel; - } - HugeVertex otherVertex = new HugeVertex(null, otherVertexId, - otherVertexLabel); - ownerVertex.propNotLoaded(); - otherVertex.propNotLoaded(); - - HugeEdge edge = new HugeEdge(null, null, edgeLabel); - edge.name(sortValues); - edge.vertices(isOutEdge, ownerVertex, otherVertex); - edge.assignId(); - - if (isOutEdge) { - ownerVertex.addOutEdge(edge); - otherVertex.addInEdge(edge.switchOwner()); - } else { - ownerVertex.addInEdge(edge); - otherVertex.addOutEdge(edge.switchOwner()); - } - - return edge; + BaseEdge element = BaseEdge.createEdgeWithoutSchema(ownerVertex.graph(), ownerVertex.element(), + isOutEdge, edgeLabel, sortValues, otherVertexId); + return attachEdge(ownerVertex, element); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdgeProperty.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdgeProperty.java index f89e4f0cf4..ab3d87587b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdgeProperty.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdgeProperty.java @@ -17,8 +17,8 @@ package org.apache.hugegraph.structure; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Property; @@ -30,6 +30,10 @@ public HugeEdgeProperty(HugeElement owner, PropertyKey key, V value) { super(owner, key, value); } + public HugeEdgeProperty(HugeElement owner, BaseProperty property) { + super(owner, property); + } + @Override public HugeType type() { return this.pkey.aggregateType().isNone() ? @@ -68,6 +72,6 @@ public int hashCode() { public HugeEdgeProperty switchEdgeOwner() { assert this.owner instanceof HugeEdge; return new HugeEdgeProperty<>(((HugeEdge) this.owner).switchOwner(), - this.pkey, this.value); + this.baseProperty()); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java index adb12f31bc..b3f46c46d3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java @@ -17,66 +17,55 @@ package org.apache.hugegraph.structure; -import java.util.ArrayList; +import java.util.AbstractCollection; import java.util.Collection; -import java.util.Date; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.function.Supplier; +import java.util.function.Consumer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.type.GraphType; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.Idfiable; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.HugeKeys; -import org.apache.hugegraph.util.CollectionUtil; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.InsertionOrderUtil; -import org.apache.hugegraph.util.collection.CollectionFactory; import org.apache.tinkerpop.gremlin.structure.Element; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.util.ElementHelper; import org.eclipse.collections.api.iterator.IntIterator; -import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; public abstract class HugeElement implements Element, GraphType, Idfiable, Comparable { - private static final MutableIntObjectMap> EMPTY_MAP = - CollectionFactory.newIntObjectMap(); - private final HugeGraph graph; - private MutableIntObjectMap> properties; - // TODO: move into properties to keep small object - private long expiredTime; - - private boolean removed; - private boolean fresh; - private boolean propLoaded; - private boolean defaultValueUpdated; public HugeElement(final HugeGraph graph) { E.checkArgument(graph != null, "HugeElement graph can't be null"); this.graph = graph; - this.properties = EMPTY_MAP; - this.expiredTime = 0L; - this.removed = false; - this.fresh = false; - this.propLoaded = true; - this.defaultValueUpdated = false; } + /** + * Shared state for internal adapters and codecs. As with setProperty(), mutations + * through this view bypass transaction callbacks; application callers must use + * the graph/TinkerPop mutation APIs to update persisted elements and indexes. + */ + public abstract BaseElement element(); + + protected abstract HugeProperty wrapProperty(BaseProperty property); + public abstract SchemaLabel schemaLabel(); protected abstract GraphTransaction tx(); @@ -89,22 +78,7 @@ protected abstract void onUpdateProperty(Cardinality cardinality, protected abstract boolean ensureFilledProperties(boolean throwIfNotExist); protected void updateToDefaultValueIfNone() { - if (this.fresh() || this.defaultValueUpdated) { - return; - } - this.defaultValueUpdated = true; - // Set default value if needed - for (Id pkeyId : this.schemaLabel().properties()) { - if (this.properties.containsKey(intFromId(pkeyId))) { - continue; - } - PropertyKey pkey = this.graph().propertyKey(pkeyId); - Object value = pkey.defaultValue(); - if (value != null) { - this.setProperty(this.newProperty(pkey, value)); - } - } - this.defaultValueUpdated = true; + this.element().updateDefaultValues(this.graph()::propertyKey); } @Override @@ -113,31 +87,31 @@ public HugeGraph graph() { } protected void removed(boolean removed) { - this.removed = removed; + this.element().removed(removed); } public boolean removed() { - return this.removed; + return this.element().removed(); } protected void fresh(boolean fresh) { - this.fresh = fresh; + this.element().fresh(fresh); } public boolean fresh() { - return this.fresh; + return this.element().fresh(); } public boolean isPropLoaded() { - return this.propLoaded; + return this.element().propLoaded(); } protected void propLoaded() { - this.propLoaded = true; + this.element().propLoaded(true); } public void propNotLoaded() { - this.propLoaded = false; + this.element().propLoaded(false); } public void forceLoad() { @@ -145,59 +119,38 @@ public void forceLoad() { } public void committed() { - this.fresh = false; + this.element().fresh(false); // Set expired time this.setExpiredTimeIfNeeded(); } public void setExpiredTimeIfNeeded() { - SchemaLabel label = this.schemaLabel(); - if (label.ttl() == 0L) { - return; - } - long now = this.graph.now(); - if (SchemaLabel.NONE_ID.equals(label.ttlStartTime())) { - this.expiredTime(now + label.ttl()); - return; - } - Date date = this.getPropertyValue(label.ttlStartTime()); - if (date == null) { - this.expiredTime(now + label.ttl()); - return; - } - long expired = date.getTime() + label.ttl(); - E.checkArgument(expired > now, - "The expired time '%s' of '%s' is prior to now: %s", - new Date(expired), this, now); - this.expiredTime(expired); + this.element().setExpiredTimeIfNeeded(this.graph.now()); } public long expiredTime() { - return this.expiredTime; + return this.element().expiredTime(); } public void expiredTime(long expiredTime) { - this.expiredTime = expiredTime; + this.element().expiredTime(expiredTime); } public boolean expired() { - return 0L < this.expiredTime && this.expiredTime < this.graph.now(); + return 0L < this.expiredTime() && this.expiredTime() < this.graph.now(); } public long ttl() { - if (this.expiredTime == 0L || this.expiredTime < this.graph.now()) { - return 0L; - } - return this.expiredTime - this.graph.now(); + return this.element().ttl(this.graph.now()); } public boolean hasTtl() { - return this.schemaLabel().ttl() > 0L; + return this.element().hasTtl(); } public Set getPropertyKeys() { Set propKeys = InsertionOrderUtil.newSet(); - IntIterator keys = this.properties.keysView().intIterator(); + IntIterator keys = this.element().properties().keysView().intIterator(); while (keys.hasNext()) { propKeys.add(IdGenerator.of(keys.next())); } @@ -205,7 +158,39 @@ public Set getPropertyKeys() { } public Collection> getProperties() { - return this.properties.values(); + Collection> properties = this.element().properties().values(); + return new AbstractCollection>() { + @Override + public Iterator> iterator() { + Iterator> iterator = properties.iterator(); + return new Iterator>() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public HugeProperty next() { + return HugeElement.this.wrapProperty(iterator.next()); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + + @Override + public int size() { + return properties.size(); + } + + @Override + public void clear() { + properties.clear(); + } + }; } public Collection> getFilledProperties() { @@ -214,17 +199,12 @@ public Collection> getFilledProperties() { } public Map getPropertiesMap() { - Map props = InsertionOrderUtil.newMap(); - for (HugeProperty prop : this.properties.values()) { - props.put(prop.propertyKey().id(), prop.value()); - } - // TODO: return MutableIntObjectMap for this method? - return props; + return this.element().getPropertiesMap(); } public Collection> getAggregateProperties() { List> aggrProps = InsertionOrderUtil.newList(); - for (HugeProperty prop : this.properties.values()) { + for (HugeProperty prop : this.getProperties()) { if (prop.type().isAggregateProperty()) { aggrProps.add(prop); } @@ -232,59 +212,40 @@ public Collection> getAggregateProperties() { return aggrProps; } - @SuppressWarnings("unchecked") public HugeProperty getProperty(Id key) { - return (HugeProperty) this.properties.get(intFromId(key)); + BaseProperty property = this.element().getProperty(key); + return property == null ? null : this.wrapProperty(property); } - @SuppressWarnings("unchecked") public V getPropertyValue(Id key) { - HugeProperty prop = this.properties.get(intFromId(key)); - if (prop == null) { - return null; - } - return (V) prop.value(); + return this.element().getPropertyValue(key); } public boolean hasProperty(Id key) { - return this.properties.containsKey(intFromId(key)); + return this.element().hasProperty(key); } public boolean hasProperties() { - return !this.properties.isEmpty(); + return this.element().hasProperties(); } public int sizeOfProperties() { - return this.properties.size(); + return this.element().sizeOfProperties(); } public int sizeOfSubProperties() { - int size = 0; - for (HugeProperty p : this.properties.values()) { - size++; - if (p.propertyKey().cardinality() != Cardinality.SINGLE && - p.value() instanceof Collection) { - size += ((Collection) p.value()).size(); - } - } - return size; + return this.element().sizeOfSubProperties(); } @Watched(prefix = "element") public HugeProperty setProperty(HugeProperty prop) { - if (this.properties == EMPTY_MAP) { - this.properties = CollectionFactory.newIntObjectMap(); - } - PropertyKey pkey = prop.propertyKey(); - - E.checkArgument(this.properties.containsKey(intFromId(pkey.id())) || - this.properties.size() < BytesBuffer.MAX_PROPERTIES, - "Exceeded the maximum number of properties"); - return this.properties.put(intFromId(pkey.id()), prop); + BaseProperty previous = this.element().addProperty(prop.baseProperty()); + return previous == null ? null : this.wrapProperty(previous); } public HugeProperty removeProperty(Id key) { - return this.properties.remove(intFromId(key)); + BaseProperty previous = this.element().removeProperty(key); + return previous == null ? null : this.wrapProperty(previous); } public HugeProperty addProperty(PropertyKey pkey, V value) { @@ -292,92 +253,30 @@ public HugeProperty addProperty(PropertyKey pkey, V value) { } @Watched(prefix = "element") - public HugeProperty addProperty(PropertyKey pkey, V value, - boolean notify) { - HugeProperty prop = null; - switch (pkey.cardinality()) { - case SINGLE: - prop = this.newProperty(pkey, value); - if (notify) { - /* - * NOTE: this method should be called before setProperty() - * because tx need to delete index without the new property - */ - this.onUpdateProperty(pkey.cardinality(), prop); - } - this.setProperty(prop); - break; - case SET: - prop = this.addProperty(pkey, value, HashSet::new); - if (notify) { - this.onUpdateProperty(pkey.cardinality(), prop); - } - break; - case LIST: - prop = this.addProperty(pkey, value, ArrayList::new); - if (notify) { - this.onUpdateProperty(pkey.cardinality(), prop); - } - break; - default: - assert false; - break; - } - return prop; - } - - @Watched(prefix = "element") - @SuppressWarnings({"rawtypes", "unchecked"}) - private HugeProperty addProperty(PropertyKey pkey, V value, - Supplier> supplier) { - assert pkey.cardinality().multiple(); - HugeProperty> property; - if (this.hasProperty(pkey.id())) { - property = this.getProperty(pkey.id()); - } else { - property = this.newProperty(pkey, supplier.get()); - this.setProperty(property); - } - - Collection values; - if (pkey.cardinality() == Cardinality.SET) { - if (value instanceof Set) { - values = (Set) value; - } else { - values = CollectionUtil.toSet(value); - } - } else { - assert pkey.cardinality() == Cardinality.LIST; - if (value instanceof List) { - values = (List) value; - } else { - values = CollectionUtil.toList(value); + public HugeProperty addProperty(PropertyKey pkey, V value, boolean notify) { + Consumer> callback = property -> { + if (notify) { + this.onUpdateProperty(pkey.cardinality(), this.wrapProperty(property)); } - } - property.value().addAll(pkey.validValueOrThrow(values)); - - // Any better ways? - return (HugeProperty) property; + }; + BaseProperty property = this.element().addProperty( + pkey, value, (key, val) -> this.newProperty(key, val).baseProperty(), + callback, callback); + return this.wrapProperty(property); } public void resetProperties() { - this.properties = CollectionFactory.newIntObjectMap(); - this.propLoaded = false; + this.element().resetProperties(); + this.element().propLoaded(false); } protected void copyProperties(HugeElement element) { - if (element.properties == EMPTY_MAP) { - this.properties = EMPTY_MAP; - } else { - this.properties = CollectionFactory.newIntObjectMap( - element.properties); - } - this.propLoaded = true; + this.element().copyProperties(element.element()); } public HugeElement copyAsFresh() { HugeElement elem = this.copy(); - elem.fresh = true; + elem.fresh(true); return elem; } @@ -512,9 +411,7 @@ public static final Object getLabelValue(Object... keyValues) { } public static int intFromId(Id id) { - E.checkArgument(id instanceof IdGenerator.LongId, - "Can't get number from %s(%s)", id, id.getClass()); - return ((IdGenerator.LongId) id).intValue(); + return BaseElement.intFromId(id); } public static final class ElementKeys { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeFeatures.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeFeatures.java index 49be0ecbe9..52b0345ebe 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeFeatures.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeFeatures.java @@ -20,7 +20,7 @@ import java.util.UUID; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.config.CoreOptions; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.VertexProperty; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeIndex.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeIndex.java deleted file mode 100644 index 6e76913935..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeIndex.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.structure; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.backend.serializer.BytesBuffer; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.type.define.DataType; -import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.HashUtil; -import org.apache.hugegraph.util.InsertionOrderUtil; -import org.apache.hugegraph.util.NumericUtil; - -public class HugeIndex implements GraphType, Cloneable { - - private final HugeGraph graph; - private Object fieldValues; - private IndexLabel indexLabel; - private Set elementIds; - private static final int HUGE_TYPE_CODE_LENGTH = 1; - - public HugeIndex(HugeGraph graph, IndexLabel indexLabel) { - E.checkNotNull(graph, "graph"); - E.checkNotNull(indexLabel, "label"); - E.checkNotNull(indexLabel.id(), "label id"); - this.graph = graph; - this.indexLabel = indexLabel; - this.elementIds = new LinkedHashSet<>(); - this.fieldValues = null; - } - - @Override - public String name() { - return this.indexLabel.name(); - } - - @Override - public HugeType type() { - if (this.indexLabel == IndexLabel.label(HugeType.VERTEX)) { - return HugeType.VERTEX_LABEL_INDEX; - } else if (this.indexLabel == IndexLabel.label(HugeType.EDGE)) { - return HugeType.EDGE_LABEL_INDEX; - } - return this.indexLabel.indexType().type(); - } - - public HugeGraph graph() { - return this.graph; - } - - public Id id() { - return formatIndexId(type(), this.indexLabelId(), this.fieldValues()); - } - - public Id hashId() { - return formatIndexHashId(type(), this.indexLabelId(), this.fieldValues()); - } - - public Object fieldValues() { - return this.fieldValues; - } - - public void fieldValues(Object fieldValues) { - this.fieldValues = fieldValues; - } - - public Id indexLabelId() { - return this.indexLabel.id(); - } - - public IndexLabel indexLabel() { - return this.indexLabel; - } - - public IdWithExpiredTime elementIdWithExpiredTime() { - E.checkState(this.elementIds.size() == 1, - "Expect one element id, actual %s", - this.elementIds.size()); - return this.elementIds.iterator().next(); - } - - public Id elementId() { - return this.elementIdWithExpiredTime().id(); - } - - public Set elementIds() { - Set ids = InsertionOrderUtil.newSet(this.elementIds.size()); - for (IdWithExpiredTime idWithExpiredTime : this.elementIds) { - ids.add(idWithExpiredTime.id()); - } - return Collections.unmodifiableSet(ids); - } - - public Set expiredElementIds() { - long now = this.graph.now(); - Set expired = InsertionOrderUtil.newSet(); - for (IdWithExpiredTime id : this.elementIds) { - if (0L < id.expiredTime && id.expiredTime < now) { - expired.add(id); - } - } - this.elementIds.removeAll(expired); - return expired; - } - - public void elementIds(Id elementId) { - this.elementIds(elementId, 0L); - } - - public void elementIds(Id elementId, long expiredTime) { - this.elementIds.add(new IdWithExpiredTime(elementId, expiredTime)); - } - - public void resetElementIds() { - this.elementIds = new LinkedHashSet<>(); - } - - public long expiredTime() { - return this.elementIdWithExpiredTime().expiredTime(); - } - - public boolean hasTtl() { - if (this.indexLabel.system()) { - return false; - } - return this.indexLabel.baseLabel().ttl() > 0L; - } - - public long ttl() { - return this.expiredTime() - this.graph.now(); - } - - @Override - public HugeIndex clone() { - try { - return (HugeIndex) super.clone(); - } catch (CloneNotSupportedException e) { - throw new HugeException("Failed to clone HugeIndex", e); - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof HugeIndex)) { - return false; - } - - HugeIndex other = (HugeIndex) obj; - return this.id().equals(other.id()); - } - - @Override - public int hashCode() { - return this.id().hashCode(); - } - - @Override - public String toString() { - return String.format("{label=%s<%s>, fieldValues=%s, elementIds=%s}", - this.indexLabel.name(), - this.indexLabel.indexType().string(), - this.fieldValues, this.elementIds); - } - - public static Id formatIndexHashId(HugeType type, Id indexLabel, - Object fieldValues) { - E.checkState(!type.isRangeIndex(), - "RangeIndex can't return a hash id"); - String value = fieldValues == null ? "" : fieldValues.toString(); - return formatIndexId(type, indexLabel, HashUtil.hash(value)); - } - - public static Id formatIndexId(HugeType type, Id indexLabelId, - Object fieldValues) { - if (type.isStringIndex()) { - String value = ""; - if (fieldValues instanceof Id) { - value = IdGenerator.asStoredString((Id) fieldValues); - } else if (fieldValues != null) { - value = fieldValues.toString(); - } - /* - * Modify order between index label and field-values to put the - * index label in front(hugegraph-1317) - */ - String strIndexLabelId = IdGenerator.asStoredString(indexLabelId); - return SplicingIdGenerator.splicing(type.string(), strIndexLabelId, value); - } else { - assert type.isRangeIndex(); - int length = type.isRange4Index() ? 4 : 8; - BytesBuffer buffer = BytesBuffer.allocate(HUGE_TYPE_CODE_LENGTH + 4 + length); - buffer.write(type.code()); - buffer.writeInt(SchemaElement.schemaId(indexLabelId)); - if (fieldValues != null) { - E.checkState(fieldValues instanceof Number, - "Field value of range index must be number:" + - " %s", fieldValues.getClass().getSimpleName()); - byte[] bytes = number2bytes((Number) fieldValues); - buffer.write(bytes); - } - return buffer.asId(); - } - } - - public static HugeIndex parseIndexId(HugeGraph graph, HugeType type, - byte[] id) { - Object values; - IndexLabel indexLabel; - if (type.isStringIndex()) { - Id idObject = IdGenerator.of(id, IdType.STRING); - String[] parts = SplicingIdGenerator.parse(idObject); - E.checkState(parts.length == 3, "Invalid secondary index id"); - Id label = IdGenerator.ofStoredString(parts[1], IdType.LONG); - indexLabel = IndexLabel.label(graph, label); - values = parts[2]; - } else { - assert type.isRange4Index() || type.isRange8Index(); - final int labelLength = 4; - E.checkState(id.length > labelLength, "Invalid range index id"); - BytesBuffer buffer = BytesBuffer.wrap(id); - buffer.read(HUGE_TYPE_CODE_LENGTH); - Id label = IdGenerator.of(buffer.readInt()); - indexLabel = IndexLabel.label(graph, label); - List fields = indexLabel.indexFields(); - E.checkState(fields.size() == 1, "Invalid range index fields"); - DataType dataType = graph.propertyKey(fields.get(0)).dataType(); - E.checkState(dataType.isNumber() || dataType.isDate(), - "Invalid range index field type"); - Class clazz = dataType.isNumber() ? - dataType.clazz() : DataType.LONG.clazz(); - values = bytes2number(buffer.read(id.length - labelLength - HUGE_TYPE_CODE_LENGTH), - clazz); - } - HugeIndex index = new HugeIndex(graph, indexLabel); - index.fieldValues(values); - return index; - } - - public static byte[] number2bytes(Number number) { - if (number instanceof Byte) { - // Handle byte as integer to store as 4 bytes in RANGE4_INDEX - number = number.intValue(); - } - return NumericUtil.numberToSortableBytes(number); - } - - public static Number bytes2number(byte[] bytes, Class clazz) { - return NumericUtil.sortableBytesToNumber(bytes, clazz); - } - - public static class IdWithExpiredTime { - - private Id id; - private long expiredTime; - - public IdWithExpiredTime(Id id, long expiredTime) { - this.id = id; - this.expiredTime = expiredTime; - } - - public Id id() { - return this.id; - } - - public long expiredTime() { - return this.expiredTime; - } - - @Override - public String toString() { - return String.format("%s(%s)", this.id, this.expiredTime); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java index 65472e148b..9cc41db401 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java @@ -19,8 +19,9 @@ import java.util.NoSuchElementException; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.type.GraphType; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Property; @@ -31,7 +32,7 @@ public abstract class HugeProperty implements Property, GraphType { protected final HugeElement owner; protected final PropertyKey pkey; - protected V value; + protected BaseProperty property; public HugeProperty(HugeElement owner, PropertyKey pkey, V value) { E.checkArgument(owner != null, "Property owner can't be null"); @@ -40,7 +41,19 @@ public HugeProperty(HugeElement owner, PropertyKey pkey, V value) { this.owner = owner; this.pkey = pkey; - this.value = pkey.validValueOrThrow(value); + this.property = new BaseProperty<>(pkey, pkey.validValueOrThrow(value)); + } + + protected HugeProperty(HugeElement owner, BaseProperty property) { + E.checkArgument(owner != null, "Property owner can't be null"); + E.checkArgument(property != null, "Property can't be null"); + this.owner = owner; + this.pkey = property.propertyKey(); + this.property = property; + } + + public BaseProperty baseProperty() { + return this.property; } public PropertyKey propertyKey() { @@ -68,16 +81,16 @@ public String key() { @Override public V value() throws NoSuchElementException { - return this.value; + return this.property.value(); } public Object serialValue(boolean encodeNumber) { - return this.pkey.serialValue(this.value, encodeNumber); + return this.property.serialValue(encodeNumber); } @Override public boolean isPresent() { - return null != this.value; + return null != this.value(); } public boolean isAggregateType() { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java index 573e2f948e..e33cd1d77c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java @@ -17,46 +17,42 @@ package org.apache.hugegraph.structure; +import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Set; +import java.util.Map; import org.apache.commons.collections.CollectionUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.id.SnowflakeIdGenerator; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; -import org.apache.hugegraph.task.HugeTask; -import org.apache.hugegraph.task.HugeTaskResult; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; -import org.apache.hugegraph.type.define.CollectionType; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.type.define.IdStrategy; import org.apache.hugegraph.util.E; -import org.apache.hugegraph.util.collection.CollectionFactory; -import org.apache.logging.log4j.util.Strings; +import org.apache.hugegraph.util.TinkerPopUtil; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; @@ -64,32 +60,20 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyVertexProperty; -import com.google.common.collect.ImmutableList; public class HugeVertex extends HugeElement implements Vertex, Cloneable { - private static final List EMPTY_LIST = ImmutableList.of(); - - /* - * Labels of the removed server info and role election vertices. Graphs - * created by older versions may still store them. - */ - private static final String LEGACY_SERVER_LABEL = Graph.Hidden.hide("server"); - private static final String LEGACY_ROLE_DATA_LABEL = Graph.Hidden.hide("role_data"); - - private Id id; - private VertexLabel label; - protected Collection edges; + private BaseVertex element; + private Map edgeWrappers; public HugeVertex(final HugeGraph graph, Id id, VertexLabel label) { super(graph); E.checkArgumentNotNull(label, "Vertex label can't be null"); - this.label = label; - - this.id = id; - this.edges = EMPTY_LIST; - if (this.id != null) { + this.element = new BaseVertex(id, label, BaseVertex.TypeContext.ENGINE); + this.element.encodeNumber(this.graph().option(CoreOptions.VERTEX_ENCODE_PK_NUMBER)); + this.edgeWrappers = new IdentityHashMap<>(); + if (this.element.id() != null) { if (label.idStrategy() == IdStrategy.CUSTOMIZE_UUID) { this.assignId(id); } else { @@ -98,56 +82,45 @@ public HugeVertex(final HugeGraph graph, Id id, VertexLabel label) { } } + /** Adopt decoded shared state without copying its property values. */ + public HugeVertex(final HugeGraph graph, BaseVertex element) { + super(graph); + E.checkArgumentNotNull(element, "Vertex element can't be null"); + E.checkArgumentNotNull(element.schemaLabel(), "Vertex label can't be null"); + this.element = element; + this.element.typeContext(BaseVertex.TypeContext.ENGINE); + this.element.encodeNumber(this.graph().option(CoreOptions.VERTEX_ENCODE_PK_NUMBER)); + this.edgeWrappers = new IdentityHashMap<>(); + if (element.id() != null) { + this.checkIdLength(); + } + } + @Override public HugeType type() { - if (label != null && - (label.name().equals(HugeTask.P.TASK) || - label.name().equals(HugeTaskResult.P.TASKRESULT))) { - return HugeType.TASK; - } - if (label != null && - (label.name().equals(LEGACY_SERVER_LABEL) || - label.name().equals(LEGACY_ROLE_DATA_LABEL))) { - return HugeType.SERVER; - } - return HugeType.VERTEX; + return this.element.type(); } @Override public Id id() { - return this.id; + return this.element.id(); } @Override public VertexLabel schemaLabel() { - assert VertexLabel.OLAP_VL.equals(this.label) || - this.graph().sameAs(this.label.graph()); - return this.label; + assert VertexLabel.OLAP_VL.equals(this.element.schemaLabel()) || + this.graph().sameAs(this.element.schemaLabel().graph()); + return this.element.schemaLabel(); } @Override public String name() { - E.checkState(this.label.idStrategy() == IdStrategy.PRIMARY_KEY, - "Only primary key vertex has name, " + - "but got '%s' with id strategy '%s'", - this, this.label.idStrategy()); - String name; - if (this.id != null) { - String[] parts = SplicingIdGenerator.parse(this.id); - E.checkState(parts.length == 2, - "Invalid primary key vertex id '%s'", this.id); - name = parts[1]; - } else { - assert this.id == null; - List propValues = this.primaryValues(); - E.checkState(!propValues.isEmpty(), - "Primary values must not be empty " + - "(has properties %s)", hasProperties()); - name = ConditionQuery.concatValues(propValues); - E.checkArgument(!name.isEmpty(), - "The value of primary key can't be empty"); - } - return name; + return this.element.name(); + } + + @Override + public BaseVertex element() { + return this.element; } public void assignId(Id id) { @@ -156,31 +129,31 @@ public void assignId(Id id) { @Watched(prefix = "vertex") public void assignId(Id id, boolean force) { - IdStrategy strategy = this.label.idStrategy(); + IdStrategy strategy = this.element.schemaLabel().idStrategy(); // Generate an id and assign switch (strategy) { case CUSTOMIZE_STRING: assert !id.number(); - this.id = id; + this.element.id(id); break; case CUSTOMIZE_NUMBER: assert id.number(); - this.id = id; + this.element.id(id); break; case CUSTOMIZE_UUID: - this.id = id.uuid() ? id : IdGenerator.of(id.asString(), true); + this.element.id(id.uuid() ? id : IdGenerator.of(id.asString(), true)); break; case PRIMARY_KEY: - this.id = SplicingIdGenerator.instance().generate(this); + this.element.id(SplicingIdGenerator.instance().generate(this.element())); break; case AUTOMATIC: if (force) { // Resume id for AUTOMATIC id strategy in restoring mode assert id.number(); - this.id = id; + this.element.id(id); } else { - this.id = SnowflakeIdGenerator.instance(this.graph()) - .generate(this); + this.element.id(SnowflakeIdGenerator.instance(this.graph()) + .generate(this.element())); } break; default: @@ -190,14 +163,14 @@ public void assignId(Id id, boolean force) { } protected void checkIdLength() { - assert this.id != null; - int len = this.id.asBytes().length; + assert this.element.id() != null; + int len = this.element.id().asBytes().length; if (len <= BytesBuffer.ID_LEN_MAX) { return; } E.checkArgument(false, "The max length of vertex id is %s, but got %s {%s}", - BytesBuffer.ID_LEN_MAX, len, this.id); + BytesBuffer.ID_LEN_MAX, len, this.element.id()); } @Override @@ -206,67 +179,67 @@ public String label() { } public void correctVertexLabel(VertexLabel correctLabel) { - E.checkArgumentNotNull(correctLabel, "Vertex label can't be null"); - if (this.label != null && !this.label.undefined() && - !correctLabel.undefined()) { - E.checkArgument(this.label.equals(correctLabel), - "Vertex label can't be changed from '%s' to '%s'", - this.label, correctLabel); - } - this.label = correctLabel; + this.element.correctVertexLabel(correctLabel); } @Watched(prefix = "vertex") protected List primaryValues() { - E.checkArgument(this.label.idStrategy() == IdStrategy.PRIMARY_KEY, - "The id strategy '%s' don't have primary keys", - this.label.idStrategy()); - List primaryKeys = this.label.primaryKeys(); - E.checkArgument(!primaryKeys.isEmpty(), - "Primary key can't be empty for id strategy '%s'", - IdStrategy.PRIMARY_KEY); - - boolean encodeNumber = this.graph() - .option(CoreOptions.VERTEX_ENCODE_PK_NUMBER); - List propValues = new ArrayList<>(primaryKeys.size()); - for (Id pk : primaryKeys) { - HugeProperty property = this.getProperty(pk); - E.checkState(property != null, - "The value of primary key '%s' can't be null", - this.graph().propertyKey(pk).name()); - Object propValue = property.serialValue(encodeNumber); - if (Strings.EMPTY.equals(propValue)) { - propValue = ConditionQuery.INDEX_VALUE_EMPTY; - } - propValues.add(propValue); - } - return propValues; + return this.element.primaryValues(); } public boolean existsEdges() { - return !this.edges.isEmpty(); + return !this.element.edges().isEmpty(); } public Collection getEdges() { - return Collections.unmodifiableCollection(this.edges); + Collection edges = this.element.edges(); + return Collections.unmodifiableCollection(new AbstractCollection() { + @Override + public Iterator iterator() { + Iterator iterator = edges.iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public HugeEdge next() { + BaseEdge edge = iterator.next(); + return HugeVertex.this.edgeWrappers.computeIfAbsent( + edge, value -> new HugeEdge(HugeVertex.this.graph(), value, + HugeVertex.this)); + } + }; + } + + @Override + public int size() { + return edges.size(); + } + }); } public void resetEdges() { - /* - * Use List to hold edges to reduce memory usage and operation time. - */ - this.edges = newList(); + this.resetEdges(false); + } + + protected void resetEdges(boolean unique) { + this.element.resetEdges(unique); + this.edgeWrappers.clear(); } public void removeEdge(HugeEdge edge) { - this.edges.remove(edge); + BaseEdge removed = this.element.removeEdge(edge.element()); + if (removed != null) { + this.edgeWrappers.remove(removed); + } } public void addEdge(HugeEdge edge) { - if (this.edges == EMPTY_LIST) { - this.edges = newList(); + if (this.element.addEdge(edge.element())) { + this.edgeWrappers.put(edge.element(), edge); } - this.edges.add(edge); } /** @@ -381,7 +354,7 @@ public void addInEdge(HugeEdge edge) { public Iterator getEdges(Directions direction, String... edgeLabels) { List list = new LinkedList<>(); - for (HugeEdge edge : this.edges) { + for (HugeEdge edge : this.getEdges()) { if (edge.matchDirection(direction) && edge.belongToLabels(edgeLabels)) { list.add(edge); @@ -404,7 +377,7 @@ public Iterator getVertices(Directions direction, @Watched(prefix = "vertex") @Override public Iterator edges(Direction tinkerpopDir, String... edgeLabels) { - Directions direction = Directions.convert(tinkerpopDir); + Directions direction = TinkerPopUtil.direction(tinkerpopDir); Id[] edgeLabelIds = this.graph().mapElName2Id(edgeLabels); Query query = GraphTransaction.constructEdgesQuery(this.id(), direction, edgeLabelIds); @@ -463,17 +436,17 @@ public VertexProperty property(VertexProperty.Cardinality cardinality, */ if (cardinality != VertexProperty.Cardinality.single) { E.checkArgument(propertyKey.cardinality() == - Cardinality.convert(cardinality), + TinkerPopUtil.cardinality(cardinality), "Invalid cardinality '%s' for property key '%s', " + "expect '%s'", cardinality, key, propertyKey.cardinality().string()); } // Check key in vertex label - E.checkArgument(VertexLabel.OLAP_VL.equals(this.label) || - this.label.properties().contains(propertyKey.id()), + E.checkArgument(VertexLabel.OLAP_VL.equals(this.element.schemaLabel()) || + this.element.schemaLabel().properties().contains(propertyKey.id()), "Invalid property '%s' for vertex label '%s'", - key, this.label); + key, this.element.schemaLabel()); // Primary-Keys can only be set once if (this.schemaLabel().primaryKeys().contains(propertyKey.id())) { E.checkArgument(!this.hasProperty(propertyKey.id()), @@ -501,6 +474,11 @@ protected HugeVertexProperty newProperty(PropertyKey pkey, V val) { return new HugeVertexProperty<>(this, pkey, val); } + @Override + protected HugeVertexProperty wrapProperty(BaseProperty property) { + return new HugeVertexProperty<>(this, property); + } + @Watched(prefix = "vertex") @Override protected void onUpdateProperty(Cardinality cardinality, @@ -543,7 +521,7 @@ protected boolean ensureFilledProperties(boolean throwIfNotExist) { if (vertex == null && !throwIfNotExist) { return false; } - E.checkState(vertex != null, "Vertex '%s' does not exist", this.id); + E.checkState(vertex != null, "Vertex '%s' does not exist", this.element.id()); if (vertex.schemaLabel().undefined() || !vertex.schemaLabel().equals(this.schemaLabel())) { // Update vertex label of dangling edge to undefined @@ -596,20 +574,7 @@ public Iterator> properties(String... keys) { @Override public Object sysprop(HugeKeys key) { - switch (key) { - case ID: - return this.id(); - case LABEL: - return this.schemaLabel().id(); - case PRIMARY_VALUES: - return this.name(); - case PROPERTIES: - return this.getPropertiesMap(); - default: - E.checkArgument(false, - "Invalid system property '%s' of Vertex", key); - return null; - } + return this.element.sysprop(key); } public boolean valid() { @@ -622,14 +587,12 @@ public boolean valid() { } /** - * Clear edges/properties of the cloned vertex, and set `removed` true + * Clear edges/properties of the cloned vertex, and set `removed` true. * * @return a new vertex */ public HugeVertex prepareRemoved() { - // NOTE: clear edges/properties of the cloned vertex and return HugeVertex vertex = this.clone(); - // Remove self vertex.removed(true); vertex.resetEdges(); vertex.resetProperties(); @@ -637,7 +600,7 @@ public HugeVertex prepareRemoved() { } public boolean olap() { - return this.label.olap(); + return this.element.schemaLabel().olap(); } @Override @@ -650,7 +613,10 @@ public HugeVertex copy() { @Override protected HugeVertex clone() { try { - return (HugeVertex) super.clone(); + HugeVertex vertex = (HugeVertex) super.clone(); + vertex.element = (BaseVertex) this.element.clone(); + vertex.edgeWrappers = new IdentityHashMap<>(this.edgeWrappers); + return vertex; } catch (CloneNotSupportedException e) { throw new HugeException("Failed to clone HugeVertex", e); } @@ -675,13 +641,7 @@ public static HugeVertex create(final GraphTransaction tx, return new HugeVertex4Insert(tx, id, label); } - private static Set newSet() { - return CollectionFactory.newSet(CollectionType.EC); - } - private static List newList() { - return CollectionFactory.newList(CollectionType.EC); - } private static final class HugeVertex4Insert extends HugeVertex { @@ -694,22 +654,14 @@ public HugeVertex4Insert(final GraphTransaction tx, * Use Set to hold edges inserted into vertex * to avoid duplicated edges */ - this.edges = newSet(); + this.resetEdges(true); this.tx = tx; this.fresh(true); } @Override public void resetEdges() { - this.edges = newSet(); - } - - @Override - public void addEdge(HugeEdge edge) { - if (this.edges == EMPTY_LIST) { - this.edges = newSet(); - } - this.edges.add(edge); + this.resetEdges(true); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertexProperty.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertexProperty.java index 4cef519799..8ef5cca262 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertexProperty.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertexProperty.java @@ -20,8 +20,8 @@ import java.util.Iterator; import org.apache.hugegraph.exception.NotSupportException; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Element; @@ -36,6 +36,10 @@ public HugeVertexProperty(HugeElement owner, PropertyKey key, V value) { super(owner, key, value); } + public HugeVertexProperty(HugeElement owner, BaseProperty property) { + super(owner, property); + } + @Override public HugeType type() { return this.pkey.aggregateType().isNone() ? diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/DistributedTaskScheduler.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/DistributedTaskScheduler.java index 4e9e0b13a4..802049eb04 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/DistributedTaskScheduler.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/DistributedTaskScheduler.java @@ -32,10 +32,10 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.ConnectionException; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/EphemeralJobQueue.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/EphemeralJobQueue.java index c7c840a882..0b2debb553 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/EphemeralJobQueue.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/EphemeralJobQueue.java @@ -25,7 +25,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.job.EphemeralJob; import org.apache.hugegraph.job.EphemeralJobBuilder; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTask.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTask.java index f63d4c0762..6d36212f56 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTask.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTask.java @@ -17,6 +17,7 @@ package org.apache.hugegraph.task; +import java.io.InterruptedIOException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -29,11 +30,11 @@ import java.util.stream.Collector; import java.util.stream.Collectors; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.LimitExceedException; import org.apache.hugegraph.exception.NotFoundException; @@ -52,6 +53,7 @@ import org.apache.tinkerpop.gremlin.structure.Graph.Hidden; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException; import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.slf4j.Logger; @@ -346,9 +348,16 @@ public boolean cancel(boolean mayInterruptIfRunning) { return cancelled; } + private static boolean isInterrupted(Throwable error) { + Throwable cause = HugeException.rootCause(error); + return cause instanceof InterruptedException || + cause instanceof TraversalInterruptedException || + cause instanceof InterruptedIOException; + } + public boolean fail(Throwable e) { E.checkNotNull(e, "exception"); - if (!(this.cancelled() && HugeException.isInterrupted(e))) { + if (!(this.cancelled() && isInterrupted(e))) { LOG.warn("An exception occurred when running task: {}", this.id(), e); // Update status to FAILED if exception occurred(not interrupted) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTaskResult.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTaskResult.java index 1c47ee9da5..9f01d60acc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTaskResult.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/HugeTaskResult.java @@ -21,7 +21,7 @@ import java.util.Iterator; import java.util.List; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.util.Blob; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/ServerInfoManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/ServerInfoManager.java index 3d3585caf4..7155913fef 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/ServerInfoManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/ServerInfoManager.java @@ -18,8 +18,8 @@ package org.apache.hugegraph.task; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.type.define.NodeRole; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/StandardTaskScheduler.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/StandardTaskScheduler.java index 3367572580..9c0d3e9d18 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/StandardTaskScheduler.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/StandardTaskScheduler.java @@ -28,13 +28,13 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.PageInfo; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.config.CoreOptions; @@ -43,8 +43,8 @@ import org.apache.hugegraph.iterator.ExtendableIterator; import org.apache.hugegraph.iterator.MapperIterator; import org.apache.hugegraph.job.EphemeralJob; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.task.HugeTask.P; import org.apache.hugegraph.task.TaskCallable.SysTaskCallable; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultScheduler.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultScheduler.java index ffb54c71b6..70ccf10ed3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultScheduler.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultScheduler.java @@ -23,16 +23,16 @@ import java.util.Map; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.iterator.ListIterator; import org.apache.hugegraph.iterator.MapperIterator; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultTransaction.java index c39ae23615..c9f766f2ef 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskAndResultTransaction.java @@ -20,13 +20,13 @@ import java.util.ArrayList; import java.util.List; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.backend.store.BackendStore; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskCallable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskCallable.java index 4e0550f5c9..5872acd9dd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskCallable.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskCallable.java @@ -21,7 +21,7 @@ import java.util.Set; import java.util.concurrent.Callable; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskManager.java index cbdc1948c2..e529897a7d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskManager.java @@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.concurrent.PausableScheduledThreadPool; import org.apache.hugegraph.util.Consumers; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskScheduler.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskScheduler.java index ea10cd006d..a4f8cbd56e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskScheduler.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskScheduler.java @@ -24,7 +24,7 @@ import java.util.concurrent.TimeoutException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; public interface TaskScheduler { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskTransaction.java index 9dd4a46aa0..74e96cd18b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskTransaction.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/task/TaskTransaction.java @@ -21,17 +21,17 @@ import java.util.Iterator; import java.util.List; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.backend.tx.GraphTransaction; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; -import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; @@ -96,7 +96,7 @@ private void removeLabelIndex(HugeVertex vertex) { return; } - HugeIndex index = new HugeIndex(this.graph(), + Index index = new Index(this.graph(), IndexLabel.label(vertex.type())); index.fieldValues(vertex.schemaLabel().id()); index.elementIds(vertex.id(), vertex.expiredTime()); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CollectionPathsTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CollectionPathsTraverser.java index c2a5ba4f79..d820dd03b4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CollectionPathsTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CollectionPathsTraverser.java @@ -24,7 +24,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; import org.apache.hugegraph.traversal.algorithm.strategy.TraverseStrategy; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CountTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CountTraverser.java index 1b9defac46..442dbaeb31 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CountTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CountTraverser.java @@ -23,7 +23,7 @@ import org.apache.commons.lang.mutable.MutableLong; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.iterator.FilterIterator; import org.apache.hugegraph.iterator.FlatMapperIterator; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizePathsTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizePathsTraverser.java index b639df2d4c..dab3d79f70 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizePathsTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizePathsTraverser.java @@ -23,7 +23,7 @@ import java.util.Map; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.steps.WeightedEdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizedCrosspointsTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizedCrosspointsTraverser.java index be3a244eb2..4c0ede0806 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizedCrosspointsTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/CustomizedCrosspointsTraverser.java @@ -25,7 +25,7 @@ import java.util.stream.Collectors; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/EdgeExistenceTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/EdgeExistenceTraverser.java index 98fbfbd9d9..d47f987e0a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/EdgeExistenceTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/EdgeExistenceTraverser.java @@ -20,10 +20,10 @@ import java.util.Iterator; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.iterator.FilterIterator; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/FusiformSimilarityTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/FusiformSimilarityTraverser.java index 741a6ef6fe..87dd7c8876 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/FusiformSimilarityTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/FusiformSimilarityTraverser.java @@ -24,8 +24,8 @@ import org.apache.commons.lang3.mutable.MutableInt; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java index fe8fa05687..a7bbdb9723 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java @@ -34,13 +34,13 @@ import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.EdgesQueryIterator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.config.CoreOptions; @@ -50,7 +50,7 @@ import org.apache.hugegraph.iterator.LimitIterator; import org.apache.hugegraph.iterator.MapperIterator; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.iterator.NestedIterator; @@ -483,7 +483,7 @@ private Iterator edgesOfVertex(Id source, EdgeStep edgeStep, if (filter != null) { ConditionQuery finalFilter = filter; edges = new FilterIterator<>(edges, (e) -> { - return finalFilter.test((HugeEdge) e); + return finalFilter.test(((HugeEdge) e).element()); }); } return edgeStep.skipSuperNodeIfNeeded(edges); @@ -544,7 +544,7 @@ private Boolean validateVertex(Map conditions, ConditionQuery cq = conditions.get(sourceV.schemaLabel().id()); if (cq != null) { sourceV = (HugeVertex) this.graph.vertex(sourceV.id()); - if (!cq.test(sourceV)) { + if (!cq.test(sourceV.element())) { return false; } } @@ -552,7 +552,7 @@ private Boolean validateVertex(Map conditions, cq = conditions.get(targetV.schemaLabel().id()); if (cq != null) { targetV = (HugeVertex) this.graph.vertex(targetV.id()); - return cq.test(targetV); + return cq.test(targetV.element()); } return true; } @@ -565,7 +565,7 @@ private Boolean validateEdge(Map conditions, ConditionQuery cq = conditions.get(edge.schemaLabel().id()); if (cq != null) { - return cq.test(edge); + return cq.test(edge.element()); } return true; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/JaccardSimilarTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/JaccardSimilarTraverser.java index 296e89ad40..37f639390d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/JaccardSimilarTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/JaccardSimilarTraverser.java @@ -22,9 +22,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.CollectionUtil; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KneighborTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KneighborTraverser.java index 2b284b26a0..a9563ee0b0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KneighborTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KneighborTraverser.java @@ -21,8 +21,8 @@ import java.util.function.Consumer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.records.KneighborRecords; import org.apache.hugegraph.traversal.algorithm.steps.Steps; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KoutTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KoutTraverser.java index 8cf3c15b7e..909457be26 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KoutTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/KoutTraverser.java @@ -22,11 +22,11 @@ import java.util.Set; import java.util.function.Consumer; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.records.KoutRecords; import org.apache.hugegraph.traversal.algorithm.steps.Steps; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/MultiNodeShortestPathTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/MultiNodeShortestPathTraverser.java index 38f899c7f3..846317d438 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/MultiNodeShortestPathTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/MultiNodeShortestPathTraverser.java @@ -26,7 +26,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/NeighborRankTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/NeighborRankTraverser.java index 914309a780..8a7149318e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/NeighborRankTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/NeighborRankTraverser.java @@ -23,7 +23,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/OltpTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/OltpTraverser.java index 44f9cf8692..6e9bae5397 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/OltpTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/OltpTraverser.java @@ -30,8 +30,8 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.EdgesQueryIterator; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.iterator.FilterIterator; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathTraverser.java index 01a075bea7..34ddf54a10 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathTraverser.java @@ -26,7 +26,7 @@ import java.util.Set; import java.util.function.BiConsumer; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.EdgeRecord; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathsTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathsTraverser.java index 5746533a50..763c6b48fa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathsTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PathsTraverser.java @@ -20,7 +20,7 @@ import java.util.Iterator; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.records.PathsRecords; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PersonalRankTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PersonalRankTraverser.java index 2c3bafa238..cd957e42ab 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PersonalRankTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PersonalRankTraverser.java @@ -24,9 +24,9 @@ import java.util.function.BiFunction; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PredictionTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PredictionTraverser.java index 4b2cb69e57..c7aa916bc4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PredictionTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/PredictionTraverser.java @@ -20,7 +20,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SameNeighborTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SameNeighborTraverser.java index af16231015..45257afd22 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SameNeighborTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SameNeighborTraverser.java @@ -23,7 +23,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.CollectionUtil; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/ShortestPathTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/ShortestPathTraverser.java index f69fd7da50..bb0ae2ba87 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/ShortestPathTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/ShortestPathTraverser.java @@ -23,7 +23,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.records.ShortestPathRecords; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SingleSourceShortestPathTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SingleSourceShortestPathTraverser.java index 0c67228abf..f751621287 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SingleSourceShortestPathTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SingleSourceShortestPathTraverser.java @@ -27,7 +27,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SubGraphTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SubGraphTraverser.java index f76f3e3771..07f1892a04 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SubGraphTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SubGraphTraverser.java @@ -23,7 +23,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/TemplatePathsTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/TemplatePathsTraverser.java index e2e99fb87c..2ad40885c4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/TemplatePathsTraverser.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/TemplatePathsTraverser.java @@ -24,7 +24,7 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; import org.apache.hugegraph.traversal.algorithm.steps.RepeatEdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/iterator/NestedIterator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/iterator/NestedIterator.java index 09d206e30d..db0109740f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/iterator/NestedIterator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/iterator/NestedIterator.java @@ -24,7 +24,7 @@ import java.util.Map; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.iterator.WrappedIterator; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/AbstractRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/AbstractRecords.java index 74f3db5ffa..08764eca29 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/AbstractRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/AbstractRecords.java @@ -17,8 +17,8 @@ package org.apache.hugegraph.traversal.algorithm.records; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.traversal.algorithm.records.record.Record; import org.apache.hugegraph.traversal.algorithm.records.record.RecordFactory; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/DoubleWayMultiPathsRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/DoubleWayMultiPathsRecords.java index 33224dc92c..a958608411 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/DoubleWayMultiPathsRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/DoubleWayMultiPathsRecords.java @@ -22,7 +22,7 @@ import java.util.Stack; import org.apache.commons.collections.CollectionUtils; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.Path; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.PathSet; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KneighborRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KneighborRecords.java index 2a4e5abb66..89940ce762 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KneighborRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KneighborRecords.java @@ -24,7 +24,7 @@ import java.util.Set; import java.util.Stack; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.PathSet; import org.apache.hugegraph.traversal.algorithm.records.record.Record; import org.apache.hugegraph.traversal.algorithm.records.record.RecordType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KoutRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KoutRecords.java index bd637ce1d4..1db6e41c2c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KoutRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/KoutRecords.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Stack; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.PathSet; import org.apache.hugegraph.traversal.algorithm.records.record.Record; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/PathsRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/PathsRecords.java index 96e04204b9..32bbb2ffe6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/PathsRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/PathsRecords.java @@ -19,7 +19,7 @@ import java.util.function.Function; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.PathSet; import org.apache.hugegraph.traversal.algorithm.records.record.RecordType; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/Records.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/Records.java index d7d4e69316..889f3e60df 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/Records.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/Records.java @@ -19,7 +19,7 @@ import java.util.function.Function; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.PathSet; public interface Records { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/ShortestPathRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/ShortestPathRecords.java index 61c081cd2d..cb7633fa9a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/ShortestPathRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/ShortestPathRecords.java @@ -22,7 +22,7 @@ import java.util.Stack; import java.util.function.Function; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.Path; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.PathSet; import org.apache.hugegraph.traversal.algorithm.records.record.Int2IntRecord; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/SingleWayMultiPathsRecords.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/SingleWayMultiPathsRecords.java index 7c3a4fd1bb..377b477670 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/SingleWayMultiPathsRecords.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/records/SingleWayMultiPathsRecords.java @@ -23,8 +23,8 @@ import java.util.Stack; import java.util.function.Function; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.EdgeRecord; import org.apache.hugegraph.traversal.algorithm.HugeTraverser.Path; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/EdgeStep.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/EdgeStep.java index caff267b7d..859cbfe9b3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/EdgeStep.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/EdgeStep.java @@ -26,8 +26,8 @@ import java.util.Map; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.optimize.TraversalUtil; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/Steps.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/Steps.java index cc4cdfacf2..7c19b4ac43 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/Steps.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/Steps.java @@ -25,9 +25,9 @@ import java.util.Map; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.optimize.TraversalUtil; import org.apache.hugegraph.type.define.Directions; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/WeightedEdgeStep.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/WeightedEdgeStep.java index b288420ff2..3385d38720 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/WeightedEdgeStep.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/steps/WeightedEdgeStep.java @@ -25,7 +25,7 @@ import java.util.Map; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.E; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/ConcurrentTraverseStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/ConcurrentTraverseStrategy.java index 235a3c2d98..6dd10c21f0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/ConcurrentTraverseStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/ConcurrentTraverseStrategy.java @@ -24,7 +24,7 @@ import java.util.function.BiConsumer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.OltpTraverser; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/SingleTraverseStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/SingleTraverseStrategy.java index 8516645cdd..680da6324d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/SingleTraverseStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/SingleTraverseStrategy.java @@ -23,7 +23,7 @@ import java.util.function.BiConsumer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.OltpTraverser; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/TraverseStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/TraverseStrategy.java index 7440133038..819d9a8f6c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/TraverseStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/strategy/TraverseStrategy.java @@ -23,7 +23,7 @@ import java.util.function.BiConsumer; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.traversal.algorithm.HugeTraverser; import org.apache.hugegraph.traversal.algorithm.steps.EdgeStep; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/ConditionP.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/ConditionP.java index 2ef93114f1..387bfab0fc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/ConditionP.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/ConditionP.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.traversal.optimize; -import org.apache.hugegraph.backend.query.Condition; +import org.apache.hugegraph.query.Condition; import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.PBiPredicate; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeCountStepStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeCountStepStrategy.java index 2dbae3bacb..2765427861 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeCountStepStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeCountStepStrategy.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.backend.query.Aggregate; +import org.apache.hugegraph.query.Aggregate; import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy.ProviderOptimizationStrategy; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeGraphStep.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeGraphStep.java index 4b7624de63..9e8b407fee 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeGraphStep.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeGraphStep.java @@ -24,8 +24,8 @@ import java.util.List; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeScriptTraversal.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeScriptTraversal.java index 0ccb48a54a..4f9233211f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeScriptTraversal.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeScriptTraversal.java @@ -25,7 +25,7 @@ import javax.script.ScriptEngine; import javax.script.ScriptException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.tinkerpop.gremlin.jsr223.SingleGremlinScriptEngineManager; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java index 33ee8570b5..1912c7b574 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.traversal.optimize; +import org.apache.hugegraph.util.TinkerPopUtil; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -24,12 +26,12 @@ import java.util.List; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.tx.GraphTransaction; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.Log; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; @@ -132,7 +134,7 @@ protected ConditionQuery constructEdgesQuery( boolean withVertexCond = this.withVertexCondition(); Id vertex = (Id) traverser.get().id(); - Directions direction = Directions.convert(this.getDirection()); + Directions direction = TinkerPopUtil.direction(this.getDirection()); EdgeLabel[] els = graph.mapElName2El(this.getEdgeLabels()); LOG.debug("HugeVertexStep.edges(): vertex={}, direction={}, " + diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStepByBatch.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStepByBatch.java index 62d6a2b921..a6fce4682d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStepByBatch.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStepByBatch.java @@ -20,9 +20,9 @@ import java.util.Iterator; import java.util.List; -import org.apache.hugegraph.backend.query.BatchConditionQuery; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.BatchConditionQuery; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.iterator.BatchMapperIterator; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/QueryHolder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/QueryHolder.java index eaa03ecc3a..10934d749f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/QueryHolder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/QueryHolder.java @@ -19,8 +19,8 @@ import java.util.Iterator; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.iterator.Metadatable; import org.apache.tinkerpop.gremlin.process.traversal.Order; import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/Text.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/Text.java index fc1d06cce4..508eac70fd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/Text.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/Text.java @@ -17,8 +17,8 @@ package org.apache.hugegraph.traversal.optimize; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; public class Text { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java index e426ee7819..d85015c97c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java @@ -29,24 +29,24 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.hugegraph.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.exception.NotSupportException; import org.apache.hugegraph.iterator.FilterIterator; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.structure.HugeProperty; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/HugeType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/HugeType.java deleted file mode 100644 index 122036ae38..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/HugeType.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.hugegraph.type.define.SerialEnum; - -public enum HugeType implements SerialEnum { - - UNKNOWN(0, "UNKNOWN"), - - /* Schema types */ - VERTEX_LABEL(1, "VL"), - EDGE_LABEL(2, "EL"), - PROPERTY_KEY(3, "PK"), - INDEX_LABEL(4, "IL"), - - META(40, "M"), - COUNTER(50, "C"), - - /* Data types */ - VERTEX(101, "V"), - // System meta - SYS_PROPERTY(102, "S"), - // Property - PROPERTY(103, "U"), - // Vertex aggregate property - AGGR_PROPERTY_V(104, "VP"), - // Edge aggregate property - AGGR_PROPERTY_E(105, "EP"), - // Olap property - OLAP(106, "AP"), - // Edge - EDGE(120, "E"), - // Edge's direction is OUT for the specified vertex - EDGE_OUT(130, "O"), - // Edge's direction is IN for the specified vertex - EDGE_IN(140, "I"), - - SECONDARY_INDEX(150, "SI"), - VERTEX_LABEL_INDEX(151, "VI"), - EDGE_LABEL_INDEX(152, "EI"), - RANGE_INT_INDEX(160, "II"), - RANGE_FLOAT_INDEX(161, "FI"), - RANGE_LONG_INDEX(162, "LI"), - RANGE_DOUBLE_INDEX(163, "DI"), - SEARCH_INDEX(170, "AI"), - SHARD_INDEX(175, "HI"), - UNIQUE_INDEX(178, "UI"), - - TASK(180, "T"), - SERVER(181, "SERVER"), - - VARIABLE(185, "VA"), - - KV_TYPE(200, "KV"), - KV_RAW(201, "KVR"), - - // System schema - SYS_SCHEMA(250, "SS"), - - MAX_TYPE(255, "~"); - - private byte type = 0; - private final String name; - - private static final Map ALL_NAME = new HashMap<>(); - - static { - SerialEnum.register(HugeType.class); - for (HugeType type : values()) { - ALL_NAME.put(type.name, type); - } - } - - HugeType(int type, String name) { - assert type < 256; - this.type = (byte) type; - this.name = name; - } - - @Override - public byte code() { - return this.type; - } - - public String string() { - return this.name; - } - - public String readableName() { - return this.name().replace('_', ' ').toLowerCase(); - } - - public boolean isSchema() { - return this == HugeType.VERTEX_LABEL || - this == HugeType.EDGE_LABEL || - this == HugeType.PROPERTY_KEY || - this == HugeType.INDEX_LABEL; - } - - public boolean isGraph() { - return this.isVertex() || this.isEdge(); - } - - public boolean isVertex() { - return this == HugeType.VERTEX || this == HugeType.TASK || this == HugeType.SERVER || - this == HugeType.VARIABLE; - } - - public boolean isEdge() { - return this == EDGE || this == EDGE_OUT || this == EDGE_IN; - } - - public boolean isEdgeLabel() { - return this == EDGE_LABEL; - } - - public boolean isIndex() { - return this == VERTEX_LABEL_INDEX || this == EDGE_LABEL_INDEX || - this == SECONDARY_INDEX || this == SEARCH_INDEX || - this == RANGE_INT_INDEX || this == RANGE_FLOAT_INDEX || - this == RANGE_LONG_INDEX || this == RANGE_DOUBLE_INDEX || - this == SHARD_INDEX || this == UNIQUE_INDEX; - } - - public boolean isLabelIndex() { - return this == VERTEX_LABEL_INDEX || this == EDGE_LABEL_INDEX; - } - - public boolean isStringIndex() { - return this == VERTEX_LABEL_INDEX || this == EDGE_LABEL_INDEX || - this == SECONDARY_INDEX || this == SEARCH_INDEX || - this == SHARD_INDEX || this == UNIQUE_INDEX; - } - - public boolean isNumericIndex() { - return this == RANGE_INT_INDEX || this == RANGE_FLOAT_INDEX || - this == RANGE_LONG_INDEX || this == RANGE_DOUBLE_INDEX || - this == SHARD_INDEX; - } - - public boolean isSecondaryIndex() { - return this == VERTEX_LABEL_INDEX || this == EDGE_LABEL_INDEX || - this == SECONDARY_INDEX; - } - - public boolean isSearchIndex() { - return this == SEARCH_INDEX; - } - - public boolean isRangeIndex() { - return this == RANGE_INT_INDEX || this == RANGE_FLOAT_INDEX || - this == RANGE_LONG_INDEX || this == RANGE_DOUBLE_INDEX; - } - - public boolean isRange4Index() { - return this == RANGE_INT_INDEX || this == RANGE_FLOAT_INDEX; - } - - public boolean isRange8Index() { - return this == RANGE_LONG_INDEX || this == RANGE_DOUBLE_INDEX; - } - - public boolean isShardIndex() { - return this == SHARD_INDEX; - } - - public boolean isUniqueIndex() { - return this == UNIQUE_INDEX; - } - - public boolean isVertexAggregateProperty() { - return this == AGGR_PROPERTY_V; - } - - public boolean isEdgeAggregateProperty() { - return this == AGGR_PROPERTY_E; - } - - public boolean isAggregateProperty() { - return this.isVertexAggregateProperty() || - this.isEdgeAggregateProperty(); - } - - public static HugeType fromString(String type) { - return ALL_NAME.get(type); - } - - public static HugeType fromCode(byte code) { - return SerialEnum.fromCode(HugeType.class, code); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Idfiable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Idfiable.java deleted file mode 100644 index 865ad50ad0..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Idfiable.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type; - -import org.apache.hugegraph.backend.id.Id; - -public interface Idfiable { - - Id id(); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Indexable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Indexable.java deleted file mode 100644 index ff3330a567..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Indexable.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type; - -import java.util.Set; - -import org.apache.hugegraph.backend.id.Id; - -public interface Indexable { - - Set indexLabels(); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Nameable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Nameable.java deleted file mode 100644 index cf8e71e6d7..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Nameable.java +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 JanusGraph 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. - -package org.apache.hugegraph.type; - -/** - * Represents an entity that can be uniquely identified by a String name. - * - * @author Matthias Broecheler (me@matthiasb.com) - */ -public interface Nameable { - - /** - * Returns the unique name of this entity. - * - * @return Name of this entity. - */ - String name(); - -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Propertiable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Propertiable.java deleted file mode 100644 index e26a356bf6..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Propertiable.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type; - -import java.util.Set; - -import org.apache.hugegraph.backend.id.Id; - -public interface Propertiable { - - Set properties(); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Typeable.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Typeable.java deleted file mode 100644 index 95a1a11d49..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Typeable.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type; - -public interface Typeable { - - // Return schema/data type - HugeType type(); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Action.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Action.java deleted file mode 100644 index 9561d52181..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Action.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum Action implements SerialEnum { - - INSERT(1, "insert"), - - APPEND(2, "append"), - - ELIMINATE(3, "eliminate"), - - DELETE(4, "delete"), - - UPDATE_IF_PRESENT(5, "update_if_present"), - - UPDATE_IF_ABSENT(6, "update_if_absent"); - - private final byte code; - private final String name; - - static { - SerialEnum.register(Action.class); - } - - Action(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public static Action fromCode(byte code) { - switch (code) { - case 1: - return INSERT; - case 2: - return APPEND; - case 3: - return ELIMINATE; - case 4: - return DELETE; - case 5: - return UPDATE_IF_PRESENT; - case 6: - return UPDATE_IF_ABSENT; - default: - throw new AssertionError("Unsupported action code: " + code); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/AggregateType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/AggregateType.java deleted file mode 100644 index 31c0f6212d..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/AggregateType.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum AggregateType implements SerialEnum { - - NONE(0, "none"), - MAX(1, "max"), - MIN(2, "min"), - SUM(3, "sum"), - OLD(4, "old"), - SET(5, "set"), - LIST(6, "list"); - - private final byte code; - private final String name; - - static { - SerialEnum.register(AggregateType.class); - } - - AggregateType(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public boolean isNone() { - return this == NONE; - } - - public boolean isMax() { - return this == MAX; - } - - public boolean isMin() { - return this == MIN; - } - - public boolean isSum() { - return this == SUM; - } - - public boolean isNumber() { - return this.isMax() || this.isMin() || this.isSum(); - } - - public boolean isOld() { - return this == OLD; - } - - public boolean isSet() { - return this == SET; - } - - public boolean isList() { - return this == LIST; - } - - public boolean isUnion() { - return this == SET || this == LIST; - } - - public boolean isIndexable() { - return this == NONE || this == MAX || this == MIN || this == OLD; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Cardinality.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Cardinality.java deleted file mode 100644 index e9d6b59bf6..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Cardinality.java +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2017 JanusGraph 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. - -package org.apache.hugegraph.type.define; - -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - -/** - * The cardinality of the values associated with given key for a particular element. - * - * @author Matthias Broecheler (me@matthiasb.com) - */ -public enum Cardinality implements SerialEnum { - - /** - * Only a single value may be associated with the given key. - */ - SINGLE(1, "single"), - - /** - * Multiple values and duplicate values may be associated with the given - * key. - */ - LIST(2, "list"), - - /** - * Multiple but distinct values may be associated with the given key. - */ - SET(3, "set"); - - private final byte code; - private final String name; - - static { - SerialEnum.register(Cardinality.class); - } - - Cardinality(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public boolean single() { - return this == SINGLE; - } - - public boolean multiple() { - return this == LIST || this == SET; - } - - public static Cardinality convert(VertexProperty.Cardinality cardinality) { - switch (cardinality) { - case single: - return SINGLE; - case list: - return LIST; - case set: - return SET; - default: - throw new AssertionError(String.format("Unrecognized cardinality: '%s'", - cardinality)); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/CollectionType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/CollectionType.java deleted file mode 100644 index e8a4cd3547..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/CollectionType.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum CollectionType implements SerialEnum { - - // Java Collection Framework - JCF(1, "jcf"), - - // Eclipse Collection - EC(2, "ec"), - - // FastUtil - FU(3, "fu"); - - private final byte code; - private final String name; - - static { - SerialEnum.register(CollectionType.class); - } - - CollectionType(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public static CollectionType fromCode(byte code) { - switch (code) { - case 1: - return JCF; - case 2: - return EC; - case 3: - return FU; - default: - throw new AssertionError( - "Unsupported collection code: " + code); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/DataType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/DataType.java deleted file mode 100644 index bc4448908d..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/DataType.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -import java.nio.ByteBuffer; -import java.time.OffsetDateTime; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; -import org.apache.hugegraph.util.Blob; -import org.apache.hugegraph.util.Bytes; -import org.apache.hugegraph.util.DateUtil; -import org.apache.hugegraph.util.JsonUtil; -import org.apache.hugegraph.util.StringEncoding; - -public enum DataType implements SerialEnum { - - UNKNOWN(0, "unknown", Object.class), - OBJECT(1, "object", Object.class), - BOOLEAN(2, "boolean", Boolean.class), - BYTE(3, "byte", Byte.class), - INT(4, "int", Integer.class), - LONG(5, "long", Long.class), - FLOAT(6, "float", Float.class), - DOUBLE(7, "double", Double.class), - TEXT(8, "text", String.class), - BLOB(9, "blob", Blob.class), - DATE(10, "date", Date.class), - UUID(11, "uuid", UUID.class); - - private final byte code; - private final String name; - private final Class clazz; - - static { - SerialEnum.register(DataType.class); - } - - DataType(int code, String name, Class clazz) { - assert code < 256; - this.code = (byte) code; - this.name = name; - this.clazz = clazz; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public Class clazz() { - return this.clazz; - } - - public boolean isText() { - return this == DataType.TEXT; - } - - public boolean isNumber() { - return this == BYTE || this == INT || this == LONG || - this == FLOAT || this == DOUBLE; - } - - public boolean isNumber4() { - // Store index value of Byte using 4 bytes - return this == BYTE || this == INT || this == FLOAT; - } - - public boolean isNumber8() { - return this == LONG || this == DOUBLE; - } - - public boolean isBlob() { - return this == DataType.BLOB; - } - - public boolean isDate() { - return this == DataType.DATE; - } - - public boolean isUUID() { - return this == DataType.UUID; - } - - public Number valueToNumber(V value) { - if (!(this.isNumber() && value instanceof Number) && - !JsonUtil.isInfinityOrNaN(value)) { - return null; - } - if (this.clazz.isInstance(value)) { - return (Number) value; - } - - Number number; - try { - switch (this) { - case BYTE: - number = Byte.valueOf(value.toString()); - break; - case INT: - number = Integer.valueOf(value.toString()); - break; - case LONG: - number = Long.valueOf(value.toString()); - break; - case FLOAT: - number = Float.valueOf(value.toString()); - break; - case DOUBLE: - number = Double.valueOf(value.toString()); - break; - default: - throw new AssertionError(String.format( - "Number type only contains Byte, Integer, " + - "Long, Float, Double, but got %s", this.clazz())); - } - } catch (NumberFormatException e) { - throw new IllegalArgumentException(String.format( - "Can't read '%s' as %s: %s", - value, this.name, e.getMessage())); - } - return number; - } - - public Date valueToDate(V value) { - if (!this.isDate()) { - return null; - } - if (value instanceof Date) { - return (Date) value; - } else if (value instanceof OffsetDateTime) { - return Date.from(((OffsetDateTime) value).toInstant()); - } else if (value instanceof Integer) { - return new Date(((Number) value).intValue()); - } else if (value instanceof Long) { - return new Date(((Number) value).longValue()); - } else if (value instanceof String) { - return DateUtil.parse((String) value); - } - return null; - } - - public UUID valueToUUID(V value) { - if (!this.isUUID()) { - return null; - } - if (value instanceof UUID) { - return (UUID) value; - } else if (value instanceof String) { - return StringEncoding.uuid((String) value); - } - return null; - } - - public Blob valueToBlob(V value) { - if (!this.isBlob()) { - return null; - } - if (value instanceof Blob) { - return (Blob) value; - } else if (value instanceof byte[]) { - return Blob.wrap((byte[]) value); - } else if (value instanceof ByteBuffer) { - return Blob.wrap(((ByteBuffer) value).array()); - } else if (value instanceof BytesBuffer) { - return Blob.wrap(((BytesBuffer) value).bytes()); - } else if (value instanceof String) { - // Only base64 string or hex string accepted - String str = ((String) value); - if (str.startsWith("0x")) { - return Blob.wrap(Bytes.fromHex(str.substring(2))); - } - return Blob.wrap(StringEncoding.decodeBase64(str)); - } else if (value instanceof List) { - List values = (List) value; - byte[] bytes = new byte[values.size()]; - for (int i = 0; i < bytes.length; i++) { - Object v = values.get(i); - if (v instanceof Byte || v instanceof Integer) { - bytes[i] = ((Number) v).byteValue(); - } else { - throw new IllegalArgumentException(String.format( - "expect byte or int value, but got '%s'", v)); - } - } - return Blob.wrap(bytes); - } - return null; - } - - public static DataType fromClass(Class clazz) { - for (DataType type : DataType.values()) { - if (type.clazz() == clazz) { - return type; - } - } - throw new HugeException("Unknown clazz '%s' for DataType", clazz); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Directions.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Directions.java deleted file mode 100644 index 1309cd89df..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Directions.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -import org.apache.hugegraph.type.HugeType; -import org.apache.tinkerpop.gremlin.structure.Direction; - -public enum Directions implements SerialEnum { - - // TODO: add NONE enum for non-directional edges - - BOTH(0, "both"), - - OUT(1, "out"), - - IN(2, "in"); - - private byte code = 0; - private String name = null; - - static { - SerialEnum.register(Directions.class); - } - - Directions(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public HugeType type() { - switch (this) { - case OUT: - return HugeType.EDGE_OUT; - case IN: - return HugeType.EDGE_IN; - default: - throw new IllegalArgumentException(String.format( - "Can't convert direction '%s' to HugeType", this)); - } - } - - public Directions opposite() { - if (this.equals(OUT)) { - return IN; - } else { - return this.equals(IN) ? OUT : BOTH; - } - } - - public Direction direction() { - switch (this) { - case OUT: - return Direction.OUT; - case IN: - return Direction.IN; - case BOTH: - return Direction.BOTH; - default: - throw new AssertionError(String.format( - "Unrecognized direction: '%s'", this)); - } - } - - public static Directions convert(Direction direction) { - switch (direction) { - case OUT: - return OUT; - case IN: - return IN; - case BOTH: - return BOTH; - default: - throw new AssertionError(String.format( - "Unrecognized direction: '%s'", direction)); - } - } - - public static Directions convert(HugeType edgeType) { - switch (edgeType) { - case EDGE_OUT: - return OUT; - case EDGE_IN: - return IN; - default: - throw new IllegalArgumentException(String.format( - "Can't convert type '%s' to Direction", edgeType)); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java deleted file mode 100644 index 2857c6e3b3..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum EdgeLabelType implements SerialEnum { - - NORMAL(1, "NORMAL"), - - PARENT(2, "PARENT"), - - SUB(3, "SUB"), - ; - - static { - SerialEnum.register(EdgeLabelType.class); - } - - private final byte code; - private final String name; - - EdgeLabelType(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public boolean normal() { - return this == NORMAL; - } - - public boolean parent() { - return this == PARENT; - } - - public boolean sub() { - return this == SUB; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java deleted file mode 100644 index 0e3536b011..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum HugeKeys { - - UNKNOWN(0, "undefined"), - - /* Column names of schema type (common) */ - ID(1, "id"), - NAME(2, "name"), - TIMESTAMP(3, "timestamp"), - SCHEMA_TYPE(4, "schema_type"), - VALUE(5, "value"), - VERSION(6, "version"), - - USER_DATA(10, "user_data"), - STATUS(11, "status"), - - /* Column names of schema type (VertexLabel) */ - ID_STRATEGY(50, "id_strategy"), - PROPERTIES(51, "properties"), - PRIMARY_KEYS(52, "primary_keys"), - INDEX_LABELS(53, "index_labels"), - NULLABLE_KEYS(54, "nullable_keys"), - ENABLE_LABEL_INDEX(55, "enable_label_index"), - - /* Column names of schema type (EdgeLabel) */ - LINKS(80, "links"), - FREQUENCY(81, "frequency"), - SOURCE_LABEL(82, "source_label"), - TARGET_LABEL(83, "target_label"), - SORT_KEYS(84, "sort_keys"), - TTL(85, "ttl"), - TTL_START_TIME(86, "ttl_start_time"), - EDGELABEL_TYPE(87, "edgelabel_type"), - PARENT_LABEL(89, "parent_label"), - - /* Column names of schema type (PropertyKey) */ - DATA_TYPE(120, "data_type"), - CARDINALITY(121, "cardinality"), - AGGREGATE_TYPE(122, "aggregate_type"), - WRITE_TYPE(123, "write_type"), - - /* Column names of schema type (IndexLabel) */ - BASE_TYPE(150, "base_type"), - BASE_VALUE(151, "base_value"), - INDEX_TYPE(152, "index_type"), - FIELDS(153, "fields"), - - /* Column names of index data */ - INDEX_NAME(180, "index_name"), - FIELD_VALUES(181, "field_values"), - INDEX_LABEL_ID(182, "index_label_id"), - ELEMENT_IDS(183, "element_ids"), - - /* Column names of data type (Vertex/Edge) */ - LABEL(200, "label"), - OWNER_VERTEX(201, "owner_vertex"), - OTHER_VERTEX(202, "other_vertex"), - PROPERTY_KEY(203, "property_key"), - PROPERTY_VALUE(204, "property_value"), - DIRECTION(205, "direction"), - SORT_VALUES(206, "sort_values"), - PRIMARY_VALUES(207, "primary_values"), - EXPIRED_TIME(208, "expired_time"), - SUB_LABEL(211, "sub_label"), - - PROPERTY_TYPE(249, "property_type"), - AGGREGATE_PROPERTIES(250, "aggregate_properties"); - - public static final long NORMAL_PROPERTY_ID = 0L; - - /* HugeKeys define */ - private byte code = 0; - private String name = null; - - HugeKeys(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java deleted file mode 100644 index da9f51313c..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum IdStrategy implements SerialEnum { - - DEFAULT(0, "default"), - - AUTOMATIC(1, "automatic"), - - PRIMARY_KEY(2, "primary_key"), - - CUSTOMIZE_STRING(3, "customize_string"), - - CUSTOMIZE_NUMBER(4, "customize_number"), - - CUSTOMIZE_UUID(5, "customize_uuid"); - - private byte code = 0; - private String name = null; - - static { - SerialEnum.register(IdStrategy.class); - } - - IdStrategy(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public boolean isAutomatic() { - return this == AUTOMATIC; - } - - public boolean isPrimaryKey() { - return this == PRIMARY_KEY; - } - - public boolean isCustomized() { - return this == CUSTOMIZE_STRING || - this == CUSTOMIZE_NUMBER || - this == CUSTOMIZE_UUID; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IndexType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IndexType.java deleted file mode 100644 index 019ac98df9..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/IndexType.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -import org.apache.hugegraph.type.HugeType; - -public enum IndexType implements SerialEnum { - - // For secondary query - SECONDARY(1, "secondary"), - - // For range query - RANGE(2, "range"), - RANGE_INT(21, "range_int"), - RANGE_FLOAT(22, "range_float"), - RANGE_LONG(23, "range_long"), - RANGE_DOUBLE(24, "range_double"), - - // For full-text query (not supported now) - SEARCH(3, "search"), - - // For prefix + range query - SHARD(4, "shard"), - - // For unique index - UNIQUE(5, "unique"); - - private byte code = 0; - private String name = null; - - static { - SerialEnum.register(IndexType.class); - } - - IndexType(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public HugeType type() { - switch (this) { - case SECONDARY: - return HugeType.SECONDARY_INDEX; - case RANGE_INT: - return HugeType.RANGE_INT_INDEX; - case RANGE_FLOAT: - return HugeType.RANGE_FLOAT_INDEX; - case RANGE_LONG: - return HugeType.RANGE_LONG_INDEX; - case RANGE_DOUBLE: - return HugeType.RANGE_DOUBLE_INDEX; - case SEARCH: - return HugeType.SEARCH_INDEX; - case SHARD: - return HugeType.SHARD_INDEX; - case UNIQUE: - return HugeType.UNIQUE_INDEX; - default: - throw new AssertionError(String.format( - "Unknown index type '%s'", this)); - } - } - - public boolean isString() { - return this == SECONDARY || this == SEARCH || - this == SHARD || this == UNIQUE; - } - - public boolean isNumeric() { - return this == RANGE_INT || this == RANGE_FLOAT || - this == RANGE_LONG || this == RANGE_DOUBLE || - this == SHARD; - } - - public boolean isSecondary() { - return this == SECONDARY; - } - - public boolean isRange() { - return this == RANGE_INT || this == RANGE_FLOAT || - this == RANGE_LONG || this == RANGE_DOUBLE; - } - - public boolean isSearch() { - return this == SEARCH; - } - - public boolean isShard() { - return this == SHARD; - } - - public boolean isUnique() { - return this == UNIQUE; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SchemaStatus.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SchemaStatus.java deleted file mode 100644 index 4a80a6a68c..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SchemaStatus.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum SchemaStatus implements SerialEnum { - - CREATED(1, "created"), - - CREATING(2, "creating"), - - REBUILDING(3, "rebuilding"), - - DELETING(4, "deleting"), - - UNDELETED(5, "undeleted"), - - INVALID(6, "invalid"); - - private byte code = 0; - private String name = null; - - static { - SerialEnum.register(SchemaStatus.class); - } - - SchemaStatus(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - public boolean ok() { - return this == CREATED; - } - - public boolean deleting() { - return this == DELETING || this == UNDELETED; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java deleted file mode 100644 index 471c0c2d70..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.type.HugeType; -import org.apache.hugegraph.util.CollectionUtil; -import org.apache.hugegraph.util.E; - -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Table; - -public interface SerialEnum { - - byte code(); - - Table, Byte, SerialEnum> TABLE = HashBasedTable.create(); - - static void register(Class clazz) { - Object enums; - try { - enums = clazz.getMethod("values").invoke(null); - } catch (Exception e) { - throw new BackendException(e); - } - for (SerialEnum e : CollectionUtil.toList(enums)) { - TABLE.put(clazz, e.code(), e); - } - } - - static T fromCode(Class clazz, byte code) { - @SuppressWarnings("unchecked") - T value = (T) TABLE.get(clazz, code); - if (value == null) { - E.checkArgument(false, "Can't construct %s from code %s", - clazz.getSimpleName(), code); - } - return value; - } - - static void registerInternalEnums() { - SerialEnum.register(Action.class); - SerialEnum.register(AggregateType.class); - SerialEnum.register(Cardinality.class); - SerialEnum.register(DataType.class); - SerialEnum.register(Directions.class); - SerialEnum.register(Frequency.class); - SerialEnum.register(HugeType.class); - SerialEnum.register(IdStrategy.class); - SerialEnum.register(IndexType.class); - SerialEnum.register(SchemaStatus.class); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/WriteType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/WriteType.java deleted file mode 100644 index ea1018eabd..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/WriteType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.type.define; - -public enum WriteType implements SerialEnum { - - // OLTP property key - OLTP(1, "oltp"), - - // OLAP property key without index - OLAP_COMMON(2, "olap_common"), - - // OLAP property key with secondary index - OLAP_SECONDARY(3, "olap_secondary"), - - // OLAP property key with range index - OLAP_RANGE(4, "olap_range"); - - private byte code = 0; - private String name = null; - - static { - SerialEnum.register(WriteType.class); - } - - WriteType(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; - } - - @Override - public byte code() { - return this.code; - } - - public String string() { - return this.name; - } - - public boolean oltp() { - return this == OLTP; - } - - public boolean olap() { - return this == OLAP_COMMON || - this == OLAP_RANGE || - this == OLAP_SECONDARY; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Blob.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Blob.java deleted file mode 100644 index 5b5d8ec6ad..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Blob.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.util; - -import java.util.Arrays; - -public class Blob implements Comparable { - - public static final Blob EMPTY = new Blob(new byte[0]); - - private final byte[] bytes; - - private Blob(byte[] bytes) { - E.checkNotNull(bytes, "bytes"); - this.bytes = bytes; - } - - public byte[] bytes() { - return this.bytes; - } - - public static Blob wrap(byte[] bytes) { - return new Blob(bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(this.bytes); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Blob)) { - return false; - } - Blob other = (Blob) obj; - return Arrays.equals(this.bytes, other.bytes); - } - - @Override - public String toString() { - String hex = Bytes.toHex(this.bytes); - StringBuilder sb = new StringBuilder(6 + hex.length()); - sb.append("Blob{").append(hex).append("}"); - return sb.toString(); - } - - @Override - public int compareTo(Blob other) { - E.checkNotNull(other, "other blob"); - return Bytes.compare(this.bytes, other.bytes); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/ConfigUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/ConfigUtil.java index 54b5392376..a67f2c5680 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/ConfigUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/ConfigUtil.java @@ -40,7 +40,7 @@ import org.apache.commons.configuration2.tree.NodeModel; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.config.HugeConfig; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Consumers.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Consumers.java index f4a7671f35..ea6e77a1ec 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Consumers.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Consumers.java @@ -33,7 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.task.TaskManager.ContextCallable; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/CopyUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/CopyUtil.java index 7a043b7cd5..cced524bbd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/CopyUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/CopyUtil.java @@ -21,7 +21,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; public final class CopyUtil { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/GZipUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/GZipUtil.java index 962d4a33a1..ef09cc2431 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/GZipUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/GZipUtil.java @@ -22,8 +22,8 @@ import java.util.zip.Inflater; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.serializer.BytesBuffer; public final class GZipUtil { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/JsonUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/JsonUtil.java index b2fce8da57..5ed4968fe6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/JsonUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/JsonUtil.java @@ -20,7 +20,7 @@ import java.io.IOException; import java.util.Date; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.io.HugeGraphSONModule; import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator; import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LZ4Util.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LZ4Util.java deleted file mode 100644 index 44de9c60f6..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LZ4Util.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.util; - -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; - -import net.jpountz.lz4.LZ4BlockInputStream; -import net.jpountz.lz4.LZ4BlockOutputStream; -import net.jpountz.lz4.LZ4Compressor; -import net.jpountz.lz4.LZ4Factory; -import net.jpountz.lz4.LZ4FastDecompressor; - -public class LZ4Util { - - protected static final float DEFAULT_BUFFER_RATIO = 1.5f; - - public static BytesBuffer compress(byte[] bytes, int blockSize) { - return compress(bytes, blockSize, DEFAULT_BUFFER_RATIO); - } - - public static BytesBuffer compress(byte[] bytes, int blockSize, float bufferRatio) { - float ratio = bufferRatio <= 0.0F ? DEFAULT_BUFFER_RATIO : bufferRatio; - LZ4Factory factory = LZ4Factory.fastestInstance(); - LZ4Compressor compressor = factory.fastCompressor(); - int initBufferSize = Math.round(bytes.length / ratio); - BytesBuffer buf = new BytesBuffer(initBufferSize); - LZ4BlockOutputStream lz4Output = new LZ4BlockOutputStream(buf, blockSize, compressor); - try { - lz4Output.write(bytes); - lz4Output.close(); - } catch (IOException e) { - throw new BackendException("Failed to compress", e); - } - // If we need to perform reading outside the method, remember to call forReadWritten() - return buf; - } - - public static BytesBuffer decompress(byte[] bytes, int blockSize) { - return decompress(bytes, blockSize, DEFAULT_BUFFER_RATIO); - } - - public static BytesBuffer decompress(byte[] bytes, int blockSize, float bufferRatio) { - float ratio = bufferRatio <= 0.0F ? DEFAULT_BUFFER_RATIO : bufferRatio; - LZ4Factory factory = LZ4Factory.fastestInstance(); - LZ4FastDecompressor decompressor = factory.fastDecompressor(); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - int initBufferSize = Math.min(Math.round(bytes.length * ratio), - BytesBuffer.maxBufferCapacity()); - BytesBuffer buf = new BytesBuffer(initBufferSize); - LZ4BlockInputStream lzInput = new LZ4BlockInputStream(bais, decompressor); - int count; - byte[] buffer = new byte[blockSize]; - try { - while ((count = lzInput.read(buffer)) != -1) { - buf.write(buffer, 0, count); - } - lzInput.close(); - } catch (IOException e) { - throw new BackendException("Failed to decompress", e); - } - // If we need to perform reading outside the method, remember to call forReadWritten() - return buf; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LockUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LockUtil.java index 0fb10989fc..c9d317634e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LockUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/LockUtil.java @@ -29,8 +29,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.concurrent.KeyLock; import org.apache.hugegraph.concurrent.LockManager; import org.apache.hugegraph.concurrent.RowLock; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Reflection.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Reflection.java index 14e7b77120..f66d051d5d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Reflection.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/Reflection.java @@ -23,7 +23,7 @@ import java.util.LinkedHashSet; import java.util.Set; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.exception.NotSupportException; import org.slf4j.Logger; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java deleted file mode 100644 index 7b10738580..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2017 JanusGraph 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. - -package org.apache.hugegraph.util; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.UUID; - -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.serializer.BytesBuffer; -import org.mindrot.jbcrypt.BCrypt; - -import com.google.common.base.CharMatcher; - -/** - * @author Matthias Broecheler (me@matthiasb.com) - * @author HugeGraph Authors - */ -public final class StringEncoding { - - private static final MessageDigest DIGEST; - private static final byte[] BYTES_EMPTY = new byte[0]; - private static final String STRING_EMPTY = ""; - private static final int BLOCK_SIZE = 4096; - private static final int BCRYPT_WORK_FACTOR = 10; - - static { - final String ALG = "SHA-256"; - try { - DIGEST = MessageDigest.getInstance(ALG); - } catch (NoSuchAlgorithmException e) { - throw new HugeException("Failed to load algorithm %s", e, ALG); - } - } - - private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder(); - private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder(); - - /** Similar to {@link StringSerializer} */ - public static int writeAsciiString(byte[] array, int offset, String value) { - E.checkArgument(CharMatcher.ascii().matchesAllOf(value), - "'%s' must be ASCII string", value); - int len = value.length(); - if (len == 0) { - array[offset++] = (byte) 0x80; - return offset; - } - - int i = 0; - do { - int c = value.charAt(i); - assert c <= 127; - byte b = (byte) c; - if (++i == len) { - // End marker - b |= 0x80; - } - array[offset++] = b; - } while (i < len); - - return offset; - } - - public static String readAsciiString(byte[] array, int offset) { - StringBuilder sb = new StringBuilder(); - int c; - do { - c = 0xFF & array[offset++]; - if (c != 0x80) { - sb.append((char) (c & 0x7F)); - } - } while ((c & 0x80) <= 0); - return sb.toString(); - } - - public static int getAsciiByteLength(String value) { - E.checkArgument(CharMatcher.ascii().matchesAllOf(value), - "'%s' must be ASCII string", value); - return value.isEmpty() ? 1 : value.length(); - } - - public static byte[] encode(String value) { - return value.getBytes(StandardCharsets.UTF_8); - } - - public static String decode(byte[] bytes) { - if (bytes.length == 0) { - return STRING_EMPTY; - } - return new String(bytes, StandardCharsets.UTF_8); - } - - public static String decode(byte[] bytes, int offset, int length) { - if (length == 0) { - return STRING_EMPTY; - } - return new String(bytes, offset, length, StandardCharsets.UTF_8); - } - - public static String encodeBase64(byte[] bytes) { - return BASE64_ENCODER.encodeToString(bytes); - } - - public static byte[] decodeBase64(String value) { - if (value.isEmpty()) { - return BYTES_EMPTY; - } - return BASE64_DECODER.decode(value); - } - - public static byte[] compress(String value) { - return compress(value, LZ4Util.DEFAULT_BUFFER_RATIO); - } - - public static byte[] compress(String value, float bufferRatio) { - BytesBuffer buf = LZ4Util.compress(encode(value), BLOCK_SIZE, bufferRatio); - return buf.bytes(); - } - - public static String decompress(byte[] value) { - return decompress(value, LZ4Util.DEFAULT_BUFFER_RATIO); - } - - public static String decompress(byte[] value, float bufferRatio) { - BytesBuffer buf = LZ4Util.decompress(value, BLOCK_SIZE, bufferRatio); - return decode(buf.array(), 0, buf.position()); - } - - public static String hashPassword(String password) { - // OWASP suggests 10 as a minimum and 12–14 for production; - // workFactor 12 is not used by default due to its 200+ ms cost. - return BCrypt.hashpw(password, BCrypt.gensalt(BCRYPT_WORK_FACTOR)); - } - - public static boolean checkPassword(String candidatePassword, String dbPassword) { - return BCrypt.checkpw(candidatePassword, dbPassword); - } - - public static String sha256(String string) { - byte[] stringBytes = encode(string); - DIGEST.reset(); - return StringEncoding.encodeBase64(DIGEST.digest(stringBytes)); - } - - public static String format(byte[] bytes) { - return String.format("%s[0x%s]", decode(bytes), Bytes.toHex(bytes)); - } - - public static UUID uuid(String value) { - E.checkArgument(value != null, "The UUID can't be null"); - try { - if (value.contains("-") && value.length() == 36) { - return UUID.fromString(value); - } - // UUID represented by hex string - E.checkArgument(value.length() == 32, "Invalid UUID string: %s", value); - String high = value.substring(0, 16); - String low = value.substring(16); - return new UUID(Long.parseUnsignedLong(high, 16), - Long.parseUnsignedLong(low, 16)); - } catch (NumberFormatException ignored) { - throw new IllegalArgumentException("Invalid UUID string: " + value); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/TinkerPopUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/TinkerPopUtil.java new file mode 100644 index 0000000000..574201a243 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/TinkerPopUtil.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.util; + +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.Directions; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; + +public final class TinkerPopUtil { + + private TinkerPopUtil() { + } + + public static Directions direction(Direction direction) { + switch (direction) { + case OUT: + return Directions.OUT; + case IN: + return Directions.IN; + case BOTH: + return Directions.BOTH; + default: + throw new AssertionError("Unknown direction: " + direction); + } + } + + public static Direction direction(Directions direction) { + switch (direction) { + case OUT: + return Direction.OUT; + case IN: + return Direction.IN; + case BOTH: + return Direction.BOTH; + default: + throw new AssertionError("Unknown direction: " + direction); + } + } + + public static Cardinality cardinality(VertexProperty.Cardinality cardinality) { + switch (cardinality) { + case single: + return Cardinality.SINGLE; + case list: + return Cardinality.LIST; + case set: + return Cardinality.SET; + default: + throw new AssertionError("Unknown cardinality: " + cardinality); + } + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java deleted file mode 100644 index eba9d4fa6e..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.util.collection; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.type.define.CollectionType; -import org.apache.hugegraph.util.E; -import org.eclipse.collections.api.map.primitive.IntObjectMap; -import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; -import org.eclipse.collections.impl.list.mutable.FastList; -import org.eclipse.collections.impl.map.mutable.UnifiedMap; -import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap; -import org.eclipse.collections.impl.set.mutable.UnifiedSet; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - -public class CollectionFactory { - - private final CollectionType type; - - public CollectionFactory() { - this.type = CollectionType.EC; - } - - public CollectionFactory(CollectionType type) { - this.type = type; - } - - public List newList() { - return newList(this.type); - } - - public List newList(int initialCapacity) { - return newList(this.type, initialCapacity); - } - - public List newList(Collection collection) { - return newList(this.type, collection); - } - - public static List newList(CollectionType type) { - switch (type) { - case EC: - return new FastList<>(); - case JCF: - return new ArrayList<>(); - case FU: - return new ObjectArrayList<>(); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static List newList(CollectionType type, - int initialCapacity) { - switch (type) { - case EC: - return new FastList<>(initialCapacity); - case JCF: - return new ArrayList<>(initialCapacity); - case FU: - return new ObjectArrayList<>(initialCapacity); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static List newList(CollectionType type, - Collection collection) { - switch (type) { - case EC: - return new FastList<>(collection); - case JCF: - return new ArrayList<>(collection); - case FU: - return new ObjectArrayList<>(collection); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public Set newSet() { - return newSet(this.type); - } - - public Set newSet(int initialCapacity) { - return newSet(this.type, initialCapacity); - } - - public Set newSet(Collection collection) { - return newSet(this.type, collection); - } - - public static Set newSet(CollectionType type) { - switch (type) { - case EC: - return new UnifiedSet<>(); - case JCF: - return new HashSet<>(); - case FU: - return new ObjectOpenHashSet<>(); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static Set newSet(CollectionType type, - int initialCapacity) { - switch (type) { - case EC: - return new UnifiedSet<>(initialCapacity); - case JCF: - return new HashSet<>(initialCapacity); - case FU: - return new ObjectOpenHashSet<>(initialCapacity); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static Set newSet(CollectionType type, - Collection collection) { - switch (type) { - case EC: - return new UnifiedSet<>(collection); - case JCF: - return new HashSet<>(collection); - case FU: - return new ObjectOpenHashSet<>(collection); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public Map newMap() { - return newMap(this.type); - } - - public Map newMap(int initialCapacity) { - return newMap(this.type, initialCapacity); - } - - public Map newMap(Map map) { - return newMap(this.type, map); - } - - public static Map newMap(CollectionType type) { - /* - * EC is faster 10%-20% than JCF, and it's more stable & less - * memory cost(size is bigger, EC is better). - */ - switch (type) { - case EC: - return new UnifiedMap<>(); - case JCF: - return new HashMap<>(); - case FU: - return new Object2ObjectOpenHashMap<>(); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static Map newMap(CollectionType type, - int initialCapacity) { - switch (type) { - case EC: - return new UnifiedMap<>(initialCapacity); - case JCF: - return new HashMap<>(initialCapacity); - case FU: - return new Object2ObjectOpenHashMap<>(initialCapacity); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static Map newMap(CollectionType type, - Map map) { - switch (type) { - case EC: - return new UnifiedMap<>(map); - case JCF: - return new HashMap<>(map); - case FU: - return new Object2ObjectOpenHashMap<>(map); - default: - throw new AssertionError( - "Unsupported collection type: " + type); - } - } - - public static MutableIntObjectMap newIntObjectMap() { - return new IntObjectHashMap<>(); - } - - public static MutableIntObjectMap newIntObjectMap( - int initialCapacity) { - return new IntObjectHashMap<>(initialCapacity); - } - - public static MutableIntObjectMap newIntObjectMap( - IntObjectMap map) { - return new IntObjectHashMap<>(map); - } - - @SuppressWarnings("unchecked") - public static MutableIntObjectMap newIntObjectMap( - Object... objects) { - IntObjectHashMap map = IntObjectHashMap.newMap(); - E.checkArgument(objects.length % 2 == 0, - "Must provide even arguments for " + - "CollectionFactory.newIntObjectMap"); - for (int i = 0; i < objects.length; i += 2) { - int key = objects[i] instanceof Id ? - (int) ((Id) objects[i]).asLong() : (int) objects[i]; - map.put(key, (V) objects[i + 1]); - } - return map; - } - - public IdSet newIdSet() { - return newIdSet(this.type); - } - - public static IdSet newIdSet(CollectionType type) { - return new IdSet(type); - } - - public static IntSet newIntSet() { - /* - * Resume to the old version like this: - * return concurrent ? new IntHashSet().asSynchronized() : - * new IntHashSet(); - */ - return new IntSet.IntSetBySegments(Integer.MAX_VALUE); - } - - public static IntMap newIntMap() { - /* - * Resume to the old version like this: - * return concurrent ? new IntIntHashMap().asSynchronized() : - * new IntIntHashMap(); - */ - return new IntMap.IntMapBySegments(Integer.MAX_VALUE); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IdSet.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IdSet.java deleted file mode 100644 index 57f3b12021..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IdSet.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.util.collection; - -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Set; - -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.iterator.ExtendableIterator; -import org.apache.hugegraph.type.define.CollectionType; -import org.eclipse.collections.api.iterator.MutableLongIterator; -import org.eclipse.collections.impl.set.mutable.primitive.LongHashSet; - -public class IdSet extends AbstractSet { - - private final LongHashSet numberIds; - private final Set nonNumberIds; - - public IdSet(CollectionType type) { - this.numberIds = new LongHashSet(); - this.nonNumberIds = CollectionFactory.newSet(type); - } - - @Override - public int size() { - return this.numberIds.size() + this.nonNumberIds.size(); - } - - @Override - public boolean isEmpty() { - return this.numberIds.isEmpty() && this.nonNumberIds.isEmpty(); - } - - @Override - public boolean contains(Object object) { - if (!(object instanceof Id)) { - return false; - } - Id id = (Id) object; - if (id.type() == Id.IdType.LONG) { - return this.numberIds.contains(id.asLong()); - } else { - return this.nonNumberIds.contains(id); - } - } - - @Override - public Iterator iterator() { - return new ExtendableIterator<>( - this.nonNumberIds.iterator(), - new EcLongIdIterator(this.numberIds.longIterator())); - } - - @Override - public boolean add(Id id) { - if (id.type() == Id.IdType.LONG) { - return this.numberIds.add(id.asLong()); - } else { - return this.nonNumberIds.add(id); - } - } - - public boolean remove(Id id) { - if (id.type() == Id.IdType.LONG) { - return this.numberIds.remove(id.asLong()); - } else { - return this.nonNumberIds.remove(id); - } - } - - @Override - public void clear() { - this.numberIds.clear(); - this.nonNumberIds.clear(); - } - - private static class EcLongIdIterator implements Iterator { - - private final MutableLongIterator iterator; - - public EcLongIdIterator(MutableLongIterator iter) { - this.iterator = iter; - } - - @Override - public boolean hasNext() { - return this.iterator.hasNext(); - } - - @Override - public Id next() { - return IdGenerator.of(this.iterator.next()); - } - - @Override - public void remove() { - this.iterator.remove(); - } - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/ObjectIntMappingFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/ObjectIntMappingFactory.java index 832ed680bc..2872b9f998 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/ObjectIntMappingFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/ObjectIntMappingFactory.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.util.collection; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/variables/HugeVariables.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/variables/HugeVariables.java index b7f2a6c58f..de1f15fa3d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/variables/HugeVariables.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/variables/HugeVariables.java @@ -33,17 +33,17 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.iterator.FilterIterator; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/gremlin-server.yaml b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/gremlin-server.yaml index 0b070c98ff..6cfdf61aef 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/gremlin-server.yaml +++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/gremlin-server.yaml @@ -37,7 +37,7 @@ scriptEngines: { org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: { classImports: [ java.lang.Math, - org.apache.hugegraph.backend.id.IdGenerator, + org.apache.hugegraph.id.IdGenerator, org.apache.hugegraph.type.define.Directions, org.apache.hugegraph.type.define.NodeRole, org.apache.hugegraph.masterelection.GlobalMasterInfo, diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/gremlin-server.yaml b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/gremlin-server.yaml index 54e9f30260..37f5735897 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/gremlin-server.yaml +++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/gremlin-server.yaml @@ -33,7 +33,7 @@ scriptEngines: { org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: { classImports: [ java.lang.Math, - org.apache.hugegraph.backend.id.IdGenerator, + org.apache.hugegraph.id.IdGenerator, org.apache.hugegraph.type.define.Directions, org.apache.hugegraph.type.define.NodeRole, org.apache.hugegraph.masterelection.GlobalMasterInfo, diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/gremlin-server.yaml b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/gremlin-server.yaml index c2eccf2b38..45a95ad7f8 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/gremlin-server.yaml +++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/gremlin-server.yaml @@ -33,7 +33,7 @@ scriptEngines: { org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: { classImports: [ java.lang.Math, - org.apache.hugegraph.backend.id.IdGenerator, + org.apache.hugegraph.id.IdGenerator, org.apache.hugegraph.type.define.Directions, org.apache.hugegraph.type.define.NodeRole, org.apache.hugegraph.masterelection.GlobalMasterInfo, diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/gremlin-server.yaml b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/gremlin-server.yaml index 09cba186d8..4e61f9674a 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/gremlin-server.yaml +++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/gremlin-server.yaml @@ -33,7 +33,7 @@ scriptEngines: { org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: { classImports: [ java.lang.Math, - org.apache.hugegraph.backend.id.IdGenerator, + org.apache.hugegraph.id.IdGenerator, org.apache.hugegraph.type.define.Directions, org.apache.hugegraph.type.define.NodeRole, org.apache.hugegraph.masterelection.GlobalMasterInfo, diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/StoreDumper.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/StoreDumper.java index 352ea0b02e..70be13b9a4 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/StoreDumper.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/StoreDumper.java @@ -21,7 +21,7 @@ import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendStore; import org.apache.hugegraph.dist.RegisterUtil; diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java index 1165fb1a93..6e87c54194 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.dist; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.ServerOptions; diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGremlinServer.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGremlinServer.java index d03f8172d4..90319aef75 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGremlinServer.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGremlinServer.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.dist; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.auth.ContextGremlinServer; import org.apache.hugegraph.event.EventHub; import org.apache.hugegraph.util.ConfigUtil; diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/RegisterUtil.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/RegisterUtil.java index 380dd996ad..4b862e822c 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/RegisterUtil.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/RegisterUtil.java @@ -24,7 +24,7 @@ import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.builder.fluent.Configurations; import org.apache.commons.configuration2.ex.ConfigurationException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.backend.serializer.SerializerFactory; import org.apache.hugegraph.backend.store.BackendProviderFactory; import org.apache.hugegraph.config.CoreOptions; diff --git a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example1.java b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example1.java index a6cda3932f..03c4a0a643 100644 --- a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example1.java +++ b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example1.java @@ -23,14 +23,14 @@ import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.tx.GraphTransaction; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.traversal.optimize.Text; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example4.java b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example4.java index 0416dd757f..3d552e19dc 100644 --- a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example4.java +++ b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/Example4.java @@ -22,10 +22,10 @@ import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.meta.MetaManager; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/ExampleUtil.java b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/ExampleUtil.java index c5f0a4206f..3bde4e4d65 100644 --- a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/ExampleUtil.java +++ b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/ExampleUtil.java @@ -21,7 +21,7 @@ import java.util.Iterator; import java.util.concurrent.TimeoutException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.dist.RegisterUtil; diff --git a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java index 278b6336bd..88dd3c6a8c 100644 --- a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java +++ b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java @@ -29,8 +29,8 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CacheManager; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.perf.PerfUtil; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/TaskExample.java b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/TaskExample.java index 2afa719b99..fef7c3676d 100644 --- a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/TaskExample.java +++ b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/TaskExample.java @@ -22,8 +22,8 @@ import org.apache.commons.collections.IteratorUtils; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.task.TaskCallable; import org.apache.hugegraph.task.TaskScheduler; diff --git a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSerializer.java b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSerializer.java index 0cfc928ab8..37b98dc037 100644 --- a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSerializer.java +++ b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSerializer.java @@ -19,7 +19,7 @@ import java.util.Arrays; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.serializer.BinarySerializer; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSessions.java b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSessions.java index 3255d092d6..d27ce99591 100644 --- a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSessions.java +++ b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseSessions.java @@ -67,8 +67,8 @@ import org.apache.hadoop.hbase.filter.PrefixFilter; import org.apache.hadoop.hbase.util.VersionInfo; import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendIterator; import org.apache.hugegraph.backend.store.BackendSession.AbstractBackendSession; import org.apache.hugegraph.backend.store.BackendSessionPool; diff --git a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseStore.java b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseStore.java index 56f7210cc8..b539fc5427 100644 --- a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseStore.java +++ b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseStore.java @@ -30,9 +30,9 @@ import org.apache.hadoop.hbase.NamespaceExistException; import org.apache.hadoop.hbase.TableExistsException; import org.apache.hadoop.hbase.TableNotFoundException; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.AbstractBackendStore; import org.apache.hugegraph.backend.store.BackendAction; import org.apache.hugegraph.backend.store.BackendEntry; diff --git a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTable.java b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTable.java index 53a8d14f65..3faeb5d3e3 100644 --- a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTable.java +++ b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTable.java @@ -37,23 +37,23 @@ import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.Result; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.backend.serializer.BinaryEntryIterator; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.backend.store.BackendTable; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.exception.NotSupportException; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.Bytes; diff --git a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTables.java b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTables.java index c3cda4031e..7535e29d01 100644 --- a/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTables.java +++ b/hugegraph-server/hugegraph-hbase/src/main/java/org/apache/hugegraph/backend/store/hbase/HbaseTables.java @@ -25,12 +25,12 @@ import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.backend.serializer.BinaryEntryIterator; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessions.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessions.java index 85d664c587..2048e7d98e 100755 --- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessions.java +++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessions.java @@ -22,7 +22,8 @@ import java.util.Set; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.BackendSession.AbstractBackendSession; @@ -183,6 +184,12 @@ public abstract BackendColumnIterator scan(String table, public abstract BackendColumnIterator getWithBatch(String table, List keys); + public BackendColumnIterator getWithBatchExact(String table, List keys) { + return BackendColumnIterator.wrap(keys.stream().map(key -> + BackendColumn.of(key.getKey(), this.get(table, key.getOwner(), key.getKey()))) + .filter(column -> column.value != null && column.value.length != 0).iterator()); + } + public abstract void merge(String table, byte[] ownerKey, byte[] key, byte[] value); diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImpl.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImpl.java index d172651393..7c3ab3dc66 100755 --- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImpl.java +++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImpl.java @@ -32,9 +32,9 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.config.CoreOptions; @@ -409,6 +409,11 @@ public void close() { } } + static BackendColumnIterator getWithBatchExact(HgStoreSession graph, String table, List keys) { + return BackendColumnIterator.wrap(graph.batchGetOwner(table, keys).stream() + .map(entry -> BackendColumn.of(entry.key(), entry.value())).iterator()); + } + /** * HstoreSession implement for hstore */ @@ -787,6 +792,12 @@ public BackendColumnIterator getWithBatch(String table, return new ColumnIterator<>(table, kvIterator); } + @Override + public BackendColumnIterator getWithBatchExact(String table, List keys) { + assert !this.hasChanges(); + return HstoreSessionsImpl.getWithBatchExact(this.graph, table, keys); + } + @Override public void merge(String table, byte[] ownerKey, byte[] key, byte[] value) { diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java index 6439096674..22cc02676b 100644 --- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java +++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java @@ -17,12 +17,13 @@ package org.apache.hugegraph.backend.store.hstore; +import org.apache.hugegraph.backend.BinaryId; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -38,16 +39,14 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; -import org.apache.hugegraph.backend.serializer.BytesBuffer; -import org.apache.hugegraph.backend.serializer.MergeIterator; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.AbstractBackendStore; import org.apache.hugegraph.backend.store.BackendAction; import org.apache.hugegraph.backend.store.BackendEntry; @@ -59,7 +58,7 @@ import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.iterator.CIter; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.type.HugeTableType; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Action; @@ -451,7 +450,7 @@ public IdPrefixQuery next() { BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID); buffer.writeId(ownerId); - return new IdPrefixQuery(cq, new BinaryBackendEntry.BinaryId( + return new IdPrefixQuery(cq, new BinaryId( buffer.bytes(), ownerId)); } @@ -566,65 +565,14 @@ public Iterator> query(List typeList, private Iterator getBackendEntryIterator( Iterator entries, Query query) { - HstoreTable table; Set olapPks = query.olapPks(); if (this.isGraphStore && !olapPks.isEmpty()) { - List> iterators = new ArrayList<>(); - for (Id pk : olapPks) { - // Construct OLAP table query query condition - Query q = this.constructOlapQueryCondition(pk, query); - table = this.table(HugeType.OLAP); - iterators.add(table.queryOlap(this.session(HugeType.OLAP), q)); - } - entries = new MergeIterator<>(entries, iterators, - BackendEntry::mergeable); + HstoreTables.OlapTable table = (HstoreTables.OlapTable) this.table(HugeType.OLAP); + entries = table.mergeEntries(this.session(HugeType.OLAP), entries, olapPks, query.paging()); } return entries; } - /** - * Reconstruct the query OLAP table query - * Due to the olap merged into one table, when writing olap data, the key has a pk added at the end. - * So when making inquiries here, it is necessary to reconstruct the pk prefix. - * Write reference BinarySerializer.writeOlapVertex - * - * @param pk - * @param query - * @return - */ - private Query constructOlapQueryCondition(Id pk, Query query) { - if (query instanceof IdQuery && !CollectionUtils.isEmpty((query).ids())) { - IdQuery q = (IdQuery) query.copy(); - Iterator iterator = q.ids().iterator(); - LinkedHashSet linkedHashSet = new LinkedHashSet<>(); - while (iterator.hasNext()) { - Id id = iterator.next(); - if (id instanceof BinaryBackendEntry.BinaryId) { - id = ((BinaryBackendEntry.BinaryId) id).origin(); - } - - // create binary id - BytesBuffer buffer = - BytesBuffer.allocate(1 + pk.length() + 1 + id.length()); - buffer.writeId(pk); - id = new BinaryBackendEntry.BinaryId( - buffer.writeId(id).bytes(), id); - linkedHashSet.add(id); - } - q.resetIds(); - q.query(linkedHashSet); - return q; - } else { - // create binary id - BytesBuffer buffer = BytesBuffer.allocate(1 + pk.length()); - pk = new BinaryBackendEntry.BinaryId( - buffer.writeId(pk).bytes(), pk); - - IdPrefixQuery idPrefixQuery = new IdPrefixQuery(HugeType.OLAP, pk); - return idPrefixQuery; - } - } - @Override public Number queryNumber(Query query) { this.checkOpened(); diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTable.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTable.java index a1baa14089..5774eeb7c6 100755 --- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTable.java +++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTable.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.backend.store.hstore; +import org.apache.hugegraph.backend.BinaryId; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -29,25 +31,25 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.backend.serializer.BinaryEntryIterator; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.backend.store.BackendTable; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.backend.store.hstore.HstoreSessions.Countable; import org.apache.hugegraph.backend.store.hstore.HstoreSessions.Session; import org.apache.hugegraph.exception.NotSupportException; @@ -210,8 +212,8 @@ public byte[] getInsertOwner(BackendEntry entry) { * @return */ protected byte[] getOwnerId(Id id) { - if (id instanceof BinaryBackendEntry.BinaryId) { - id = ((BinaryBackendEntry.BinaryId) id).origin(); + if (id instanceof BinaryId) { + id = ((BinaryId) id).origin(); } if (id != null && id.edge()) { id = ((EdgeId) id).ownerVertexId(); diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTables.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTables.java index fe8c324f19..54b721d325 100644 --- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTables.java +++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreTables.java @@ -18,12 +18,28 @@ package org.apache.hugegraph.backend.store.hstore; import java.util.List; - -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.ConditionQuery; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Collections; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.nio.ByteBuffer; + +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.backend.BinaryId; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.OlapKey; +import org.apache.hugegraph.iterator.FlatMapperIterator; +import org.apache.hugegraph.iterator.WrappedIterator; +import org.apache.hugegraph.store.HgOwnerKey; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.serializer.BinarySerializer; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.hstore.HstoreSessions.Session; @@ -124,7 +140,7 @@ public void delete(Session session, BackendEntry entry) { * Regular index delete will call eliminate() */ byte[] ownerKey = super.ownerDelegate.apply(entry); - for (BackendEntry.BackendColumn column : entry.columns()) { + for (BackendColumn column : entry.columns()) { // Don't assert entry.belongToMe(column), length-prefix is 1* session.deletePrefix(this.table(), ownerKey, column.name); } @@ -197,17 +213,207 @@ protected BackendColumnIterator queryByCond(Session session, public static class OlapTable extends HstoreTable { public static final String TABLE = HugeTableType.OLAP_TABLE.string(); + private static final int MAX_REQUEST_KEYS = 1024; + private static final int MAX_SELECTED_VERTICES = 128; public OlapTable(String database) { // Originally multiple ap_{pk_id} merged into one ap table super(database, TABLE); } + @Override + public void insert(Session session, BackendEntry entry) { + E.checkArgumentNotNull(entry.subId(), "Merged OLAP write requires a property ID"); + byte[] owner = this.getInsertOwner(entry); + for (BackendColumn column : entry.columns()) { + E.checkArgument(OlapKey.matchesProperty(column.value, entry.subId()), + "OLAP value must match property ID '%s'", entry.subId()); + session.put(this.table(), owner, OlapKey.format(entry.subId(), entry.originId()), column.value); + } + } + + @Override + public void insert(Session session, BackendEntry entry, boolean isEdge) { + this.insert(session, entry); + } + + @Override + public void delete(Session session, BackendEntry entry) { + E.checkArgumentNotNull(entry.subId(), "Merged OLAP delete requires a property ID"); + byte[] owner = this.getInsertOwner(entry); + session.delete(this.table(), owner, OlapKey.format(entry.subId(), entry.originId())); + // Delete an old vertex-only record only if it belongs to the requested property. + byte[] legacyKey = BytesBuffer.allocate(entry.originId().length() + 9) + .writeId(entry.originId()).bytes(); + if (OlapKey.matchesProperty(session.get(this.table(), owner, legacyKey), entry.subId())) { + session.delete(this.table(), owner, legacyKey); + } + } + + @Override + public boolean queryExist(Session session, BackendEntry entry) { + E.checkArgumentNotNull(entry.subId(), "Merged OLAP existence query requires a property ID"); + Id key = new BinaryId(OlapKey.format(entry.subId(), entry.originId()), entry.originId()); + try (BackendColumnIterator result = this.getById(session, key)) { + return result.hasNext(); + } + } + + @Override + protected BackendColumnIterator queryBy(Session session, Query query) { + if (!query.ids().isEmpty() && query.conditions().isEmpty()) { + return BackendColumnIterator.wrap(new FlatMapperIterator<>( + query.ids().iterator(), id -> this.getById(session, id))); + } + return super.queryBy(session, query); + } + + @Override + protected BackendColumnIterator getById(Session session, Id id) { + // This query key is explicitly constructed by HstoreStore for the merged OLAP table. + BytesBuffer key = BytesBuffer.wrap(id.asBytes()); + Id propertyId = key.readId(); + Id vertexId = key.readId(); + byte[] owner = this.getOwnerId(id instanceof BinaryId ? ((BinaryId) id).origin() : vertexId); + byte[] value = session.get(this.table(), owner, id.asBytes()); + if (value == null || value.length == 0) { + byte[] legacyKey = BytesBuffer.allocate(vertexId.length() + 9).writeId(vertexId).bytes(); + value = session.get(this.table(), owner, legacyKey); + } + if (!OlapKey.matchesProperty(value, propertyId)) { + return BackendColumnIterator.empty(); + } + // Normalize only the returned key, so the existing OLAP entry parser retains vertex origin. + return BackendColumnIterator.iterator(BackendColumn.of(id.asBytes(), value)); + } + @Override protected BackendColumnIterator queryById(Session session, Id id) { return this.getById(session, id); } + Iterator mergeEntries(Session session, Iterator entries, + Set properties, boolean paging) { + if (properties == null || properties.isEmpty()) { + return entries; + } + return new WrappedIterator() { + private Iterator batch = Collections.emptyIterator(); + private final int batchSize = paging ? 1 : (int) Math.max(1L, Math.min( + MAX_SELECTED_VERTICES, MAX_REQUEST_KEYS / (properties.size() + 1L))); + private boolean closed; + + @Override + public void close() throws Exception { + if (!this.closed) { + this.closed = true; + this.current = none(); + this.batch = Collections.emptyIterator(); + super.close(); + } + } + + @Override + protected Iterator originIterator() { + return entries; + } + + @Override + protected boolean fetch() { + if (this.closed) { + return false; + } + try { + return this.fetchBatch(); + } catch (RuntimeException | Error failure) { + try { + this.close(); + } catch (Exception closeFailure) { + failure.addSuppressed(closeFailure); + } + throw failure; + } + } + + private boolean fetchBatch() { + if (!this.batch.hasNext()) { + List selected = new ArrayList<>(this.batchSize); + while (selected.size() < this.batchSize && entries.hasNext()) { + selected.add(entries.next()); + } + if (selected.isEmpty()) { + WrappedIterator.close(this); + return false; + } + this.mergeSelected(selected); + this.batch = selected.iterator(); + } + this.current = this.batch.next(); + return true; + } + + private void mergeSelected(List selected) { + Map legacy = new HashMap<>(); + Iterator remaining = properties.iterator(); + boolean firstChunk = true; + do { + int capacity = Math.min(MAX_REQUEST_KEYS, + selected.size() * (Math.min(properties.size(), MAX_REQUEST_KEYS) + 1)); + List keys = new ArrayList<>(capacity); + if (firstChunk) { + for (BackendEntry entry : selected) { + Id vertexId = entry.originId(); + byte[] key = BytesBuffer.allocate(vertexId.length() + 9).writeId(vertexId).bytes(); + keys.add(HgOwnerKey.of(OlapTable.this.getOwnerId(vertexId), key)); + } + } + int propertyLimit = (MAX_REQUEST_KEYS - keys.size()) / selected.size(); + List requestedProperties = new ArrayList<>(Math.min(propertyLimit, properties.size())); + while (requestedProperties.size() < propertyLimit && remaining.hasNext()) { + Id property = remaining.next(); + requestedProperties.add(property); + for (BackendEntry entry : selected) { + Id vertexId = entry.originId(); + keys.add(HgOwnerKey.of(OlapTable.this.getOwnerId(vertexId), + OlapKey.format(property, vertexId))); + } + } + Map values = new HashMap<>(); + try (BackendColumnIterator columns = session.getWithBatchExact(OlapTable.this.table(), keys)) { + while (columns.hasNext()) { + BackendColumn column = columns.next(); + values.put(ByteBuffer.wrap(column.name), column); + } + } + if (firstChunk) { + for (BackendEntry entry : selected) { + Id vertexId = entry.originId(); + byte[] key = BytesBuffer.allocate(vertexId.length() + 9).writeId(vertexId).bytes(); + legacy.put(vertexId, values.get(ByteBuffer.wrap(key))); + } + firstChunk = false; + } + for (BackendEntry entry : selected) { + Id vertexId = entry.originId(); + for (Id property : requestedProperties) { + byte[] key = OlapKey.format(property, vertexId); + BackendColumn column = values.get(ByteBuffer.wrap(key)); + if (column == null || column.value == null || column.value.length == 0) { + column = legacy.get(vertexId); + } + if (column == null || !OlapKey.matchesProperty(column.value, property)) { + continue; + } + BinaryBackendEntry olap = new BinaryBackendEntry(entry.type(), key, false, true); + olap.columns(BackendColumn.of(key, column.value)); + E.checkState(entry.mergeable(olap), "OLAP row must belong to its selected vertex"); + } + } + } while (remaining.hasNext()); + } + }; + } + @Override public boolean isOlap() { return true; diff --git a/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImplTest.java b/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImplTest.java index b962ae0b0d..dd15724c23 100644 --- a/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImplTest.java +++ b/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreSessionsImplTest.java @@ -20,14 +20,19 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; +import java.lang.reflect.Proxy; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.store.HgKvEntry; +import org.apache.hugegraph.store.HgStoreSession; +import org.apache.hugegraph.store.HgOwnerKey; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.OlapKey; import org.apache.hugegraph.store.HgKvIterator; import org.junit.Assert; import org.junit.Test; @@ -71,6 +76,30 @@ public void testColumnIteratorClearsPositionWhenFullyExhausted() Assert.assertNull(iterator.position()); } + @Test + public void testExactOlapBatchUsesNativePointKeysAndOwnerRouting() { + byte[] vertexOwner = IdGenerator.of(9).asBytes(); + byte[] namespaced = OlapKey.format(IdGenerator.of(9), IdGenerator.of(9)); + List keys = List.of(HgOwnerKey.of(vertexOwner, namespaced)); + int[] calls = {0}; + HgStoreSession graph = (HgStoreSession) Proxy.newProxyInstance(HgStoreSession.class.getClassLoader(), + new Class[]{HgStoreSession.class}, (proxy, method, args) -> { + Assert.assertEquals("batchGetOwner", method.getName()); + Assert.assertEquals("g+olap", args[0]); + Assert.assertSame(keys, args[1]); + Assert.assertArrayEquals(vertexOwner, keys.get(0).getOwner()); + Assert.assertArrayEquals(namespaced, keys.get(0).getKey()); + calls[0]++; + return List.of(new TestEntry(namespaced)); + }); + try (BackendColumnIterator result = HstoreSessionsImpl.getWithBatchExact(graph, "g+olap", keys)) { + Assert.assertTrue(result.hasNext()); + Assert.assertArrayEquals(namespaced, result.next().name); + Assert.assertFalse(result.hasNext()); + } + Assert.assertEquals(1, calls[0]); + } + private static BackendColumnIterator newColumnIterator( HgKvIterator iterator) throws Exception { Class clazz = Class.forName(HstoreSessionsImpl.class.getName() + diff --git a/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreTableTest.java b/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreTableTest.java index 79791daae1..0ae351548e 100644 --- a/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreTableTest.java +++ b/hugegraph-server/hugegraph-hstore/src/test/java/org/apache/hugegraph/backend/store/hstore/HstoreTableTest.java @@ -18,23 +18,45 @@ package org.apache.hugegraph.backend.store.hstore; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.LinkedHashSet; +import java.nio.ByteBuffer; +import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id.IdType; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.backend.BinaryId; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; +import org.apache.hugegraph.backend.serializer.BinarySerializer; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.OlapKey; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.config.ConfigOption; +import org.apache.hugegraph.iterator.CIter; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.WriteType; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.query.IdQuery; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.store.HgOwnerKey; @@ -216,6 +238,343 @@ public void testPrefixListQueryPushesCopyAndKeepsOrigin() { Assert.assertNull(pushed.originQuery()); } + @Test + public void testMergedOlapInsertPreservesStandaloneEntryAndIsolatesProperties() { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + BinaryBackendEntry score = olapEntry(9, 1, 99); + BinaryBackendEntry rank = olapEntry(10, 1, 123); + byte[] standaloneKey = score.columns().iterator().next().name; + table.insert(session, score, false); // Actual HstoreStore.mutate entry point. + table.insert(session, rank); + Assert.assertEquals(2, session.values.size()); + Assert.assertArrayEquals(standaloneKey, score.columns().iterator().next().name); + Assert.assertNull(session.values.get(ByteBuffer.wrap(standaloneKey))); + Assert.assertTrue(OlapKey.matchesProperty(session.values.get(ByteBuffer.wrap( + OlapKey.format(IdGenerator.of(9), IdGenerator.of(1)))), IdGenerator.of(9))); + for (byte[] owner : session.owners) { + Assert.assertArrayEquals(IdGenerator.of(1).asBytes(), owner); + } + } + + @Test + public void testOlapPointFallbackAndDeleteValidateLegacyPropertyIdentity() { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + BinaryBackendEntry legacy = olapEntry(9, 1, 42); + BackendColumn old = legacy.columns().iterator().next(); + session.values.put(ByteBuffer.wrap(old.name), old.value); + Id scoreKey = new BinaryId(OlapKey.format(IdGenerator.of(9), IdGenerator.of(1)), IdGenerator.of(1)); + Id rankKey = new BinaryId(OlapKey.format(IdGenerator.of(10), IdGenerator.of(1)), IdGenerator.of(1)); + try (BackendColumnIterator result = table.getById(session, scoreKey)) { + Assert.assertTrue(result.hasNext()); + Assert.assertArrayEquals(scoreKey.asBytes(), result.next().name); + } + try (BackendColumnIterator result = table.getById(session, rankKey)) { + Assert.assertFalse(result.hasNext()); + } + IdQuery query = new IdQuery(HugeType.VERTEX); + query.query(scoreKey); + query.query(rankKey); + Iterator queried = table.queryOlap(session, query); + Assert.assertTrue(queried.hasNext()); + Assert.assertEquals(IdGenerator.of(1), queried.next().originId()); + Assert.assertFalse(queried.hasNext()); + table.delete(session, olapEntry(10, 1, 123)); + Assert.assertNotNull(session.values.get(ByteBuffer.wrap(old.name))); + table.delete(session, legacy); + Assert.assertNull(session.values.get(ByteBuffer.wrap(old.name))); + } + + @Test + public void testOlapConditionalUpdatesUsePropertyScopedExistenceForOldAndNewRows() { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + BinaryBackendEntry oldScore = olapEntry(9, 1, 42); + BackendColumn old = oldScore.columns().iterator().next(); + session.values.put(ByteBuffer.wrap(old.name), old.value); + BinaryBackendEntry score = olapEntry(9, 1, 99); + BinaryBackendEntry rank = olapEntry(10, 1, 123); + byte[] scoreKey = OlapKey.format(IdGenerator.of(9), IdGenerator.of(1)); + byte[] rankKey = OlapKey.format(IdGenerator.of(10), IdGenerator.of(1)); + Assert.assertTrue(table.queryExist(session, score)); + Assert.assertFalse(table.queryExist(session, rank)); + table.updateIfPresent(session, rank); + Assert.assertNull(session.values.get(ByteBuffer.wrap(rankKey))); + table.updateIfAbsent(session, rank); + Assert.assertNotNull(session.values.get(ByteBuffer.wrap(rankKey))); + table.updateIfPresent(session, score); + Assert.assertArrayEquals(score.columns().iterator().next().value, + session.values.get(ByteBuffer.wrap(scoreKey))); + table.updateIfAbsent(session, olapEntry(9, 1, 101)); + Assert.assertArrayEquals(score.columns().iterator().next().value, + session.values.get(ByteBuffer.wrap(scoreKey))); + Assert.assertArrayEquals(old.value, session.values.get(ByteBuffer.wrap(old.name))); + table.delete(session, score); + Assert.assertFalse(table.queryExist(session, score)); + Assert.assertTrue(table.queryExist(session, rank)); + table.updateIfPresent(session, score); + Assert.assertNull(session.values.get(ByteBuffer.wrap(scoreKey))); + Assert.assertEquals(1, session.values.size()); + } + + @Test + public void testOlapMergeBatchesOnlySelectedVerticesAndPrefersNamespacedRows() throws Exception { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + BinaryBackendEntry legacy = olapEntry(9, 1, 42); + BackendColumn old = legacy.columns().iterator().next(); + session.values.put(ByteBuffer.wrap(old.name), old.value); + table.insert(session, olapEntry(9, 1, 99)); + table.insert(session, olapEntry(10, 1, 123)); + BackendColumn legacySecond = olapEntry(9, 2, 43).columns().iterator().next(); + session.values.put(ByteBuffer.wrap(legacySecond.name), legacySecond.value); + List base = new ArrayList<>(); + for (int i = 1; i <= 130; i++) { + base.add(vertexEntry(i)); + } + EntrySource source = new EntrySource(base); + Iterator merged = table.mergeEntries(session, source, + Set.of(IdGenerator.of(9), IdGenerator.of(10)), false); + Assert.assertEquals(3, merged.next().columnsSize()); + Assert.assertEquals(1, session.batchCalls); + Assert.assertEquals(128 * 3, session.requested.get(0).size()); + for (HgOwnerKey key : session.requested.get(0)) { + Assert.assertFalse(Arrays.equals(key.getOwner(), IdGenerator.of(129).asBytes())); + } + int count = 1; + while (merged.hasNext()) { + Assert.assertEquals(IdGenerator.of(++count), merged.next().originId()); + } + Assert.assertEquals(130, count); + Assert.assertEquals(2, base.get(1).columnsSize()); // Legacy score must not also be merged as rank. + Assert.assertEquals(1, base.get(2).columnsSize()); + Assert.assertEquals(2, session.batchCalls); + Assert.assertEquals(2, session.batchCloses); + Assert.assertEquals(1, source.closes); + BackendColumn score = base.get(0).columns().stream() + .filter(column -> Arrays.equals(column.name, OlapKey.format(IdGenerator.of(9), IdGenerator.of(1)))) + .findFirst().get(); + Assert.assertArrayEquals(olapEntry(9, 1, 99).columns().iterator().next().value, score.value); + // The old row remains unchanged and has not been rewritten during reads. + Assert.assertArrayEquals(old.value, session.values.get(ByteBuffer.wrap(old.name))); + } + + @Test + public void testOlapMergeCapsTotalKeysForManyPropertiesAndRetainsLastChunkRows() throws Exception { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + Set properties = manyOlapProperties(); + BackendColumn old = olapEntry(9999, 1, 42).columns().iterator().next(); + session.values.put(ByteBuffer.wrap(old.name), old.value); + table.insert(session, olapEntry(10000, 1, 99)); + EntrySource source = new EntrySource(List.of(vertexEntry(1), vertexEntry(2))); + Iterator merged = table.mergeEntries(session, source, properties, false); + BackendEntry first = merged.next(); + Assert.assertEquals(1, source.consumed); // Many properties reduce the selected vertex batch. + Assert.assertEquals(3, first.columnsSize()); + Assert.assertEquals(10, session.batchCalls); + Assert.assertEquals(10, session.batchCloses); + int oldRequests = 0; + for (List requested : session.requested) { + Assert.assertTrue(requested.size() <= 1024); + for (HgOwnerKey key : requested) { + Assert.assertArrayEquals(IdGenerator.of(1).asBytes(), key.getOwner()); + if (Arrays.equals(old.name, key.getKey())) { + oldRequests++; + } + } + } + Assert.assertEquals(1, oldRequests); + BinaryBackendEntry decoded = (BinaryBackendEntry) first; + Assert.assertArrayEquals(old.value, decoded.column( + OlapKey.format(IdGenerator.of(9999), IdGenerator.of(1))).value); + Assert.assertArrayEquals(olapEntry(10000, 1, 99).columns().iterator().next().value, + decoded.column(OlapKey.format(IdGenerator.of(10000), IdGenerator.of(1))).value); + ((AutoCloseable) merged).close(); + Assert.assertEquals(1, source.closes); + Assert.assertEquals(1, source.consumed); + } + + @Test + public void testOlapPropertyChunksCloseOnLaterBatchFailureWithoutReadingAhead() { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + session.failBatchAt = 3; + EntrySource source = new EntrySource(List.of(vertexEntry(1), vertexEntry(2))); + Iterator merged = table.mergeEntries(session, source, manyOlapProperties(), true); + try { + merged.hasNext(); + Assert.fail("A later property chunk failure must propagate"); + } catch (IllegalStateException expected) { + Assert.assertEquals("batch failed", expected.getMessage()); + } + Assert.assertEquals(1, source.consumed); + Assert.assertEquals(1, source.closes); + Assert.assertEquals(3, session.batchCalls); + Assert.assertEquals(3, session.batchCloses); + for (List requested : session.requested) { + Assert.assertTrue(requested.size() <= 1024); + } + } + + private static Set manyOlapProperties() { + Set properties = new LinkedHashSet<>(); + for (int i = 1; i <= 10000; i++) { + properties.add(IdGenerator.of(i)); + } + return properties; + } + + @Test + public void testOlapMergePreservesPagingMetadataAndClosesOnEarlyCloseOrFailure() throws Exception { + HstoreTables.OlapTable table = new HstoreTables.OlapTable("g"); + OlapSession session = new OlapSession(); + EntrySource source = new EntrySource(List.of(vertexEntry(1), vertexEntry(2))); + Iterator merged = table.mergeEntries(session, source, Set.of(IdGenerator.of(9)), true); + Assert.assertEquals(IdGenerator.of(1), merged.next().originId()); + Assert.assertEquals(1, source.consumed); + Assert.assertEquals(1, ((CIter) merged).metadata("position")); + ((AutoCloseable) merged).close(); + Assert.assertEquals(1, source.closes); + Assert.assertEquals(1, session.batchCloses); + Assert.assertFalse(merged.hasNext()); + EntrySource failed = new EntrySource(List.of(vertexEntry(1))); + session.failBatch = true; + Iterator failure = table.mergeEntries(session, failed, Set.of(IdGenerator.of(9)), false); + try { + failure.hasNext(); + Assert.fail("Native batch failure must propagate"); + } catch (IllegalStateException expected) { + Assert.assertEquals("batch failed", expected.getMessage()); + } + Assert.assertEquals(1, failed.closes); + Assert.assertEquals(2, session.batchCloses); + EntrySource empty = new EntrySource(List.of(vertexEntry(1))); + Assert.assertSame(empty, table.mergeEntries(session, empty, Set.of(), false)); + Assert.assertSame(empty, table.mergeEntries(session, empty, null, false)); + Assert.assertEquals(2, session.batchCalls); + } + + private static BinaryBackendEntry vertexEntry(int vertex) { + BinaryBackendEntry entry = new BinaryBackendEntry(HugeType.VERTEX, + BytesBuffer.allocate(16).writeId(IdGenerator.of(vertex)).bytes()); + entry.column(entry.id().asBytes(), new byte[]{0}); + return entry; + } + + private static BinaryBackendEntry olapEntry(int property, int vertex, int value) { + HugeConfig config = new HugeConfig(Map.of()); + HugeGraph graph = (HugeGraph) Proxy.newProxyInstance(HugeGraph.class.getClassLoader(), + new Class[]{HugeGraph.class}, (proxy, method, args) -> { + if (method.getName().equals("option")) { + return ((ConfigOption) args[0]).defaultValue(); + } + if (method.getName().equals("configuration")) { + return config; + } + return null; + }); + PropertyKey key = new PropertyKey(graph, IdGenerator.of(property), "property" + property); + key.dataType(DataType.INT); + key.writeType(WriteType.OLAP_COMMON); + HugeVertex olap = new HugeVertex(graph, IdGenerator.of(vertex), VertexLabel.OLAP_VL); + olap.addProperty(key, value); + return (BinaryBackendEntry) new BinarySerializer(config).writeOlapVertex(olap); + } + + private static final class EntrySource implements CIter { + private final Iterator source; + private int consumed; + private int closes; + + private EntrySource(List entries) { + this.source = entries.iterator(); + } + + @Override + public boolean hasNext() { + return this.source.hasNext(); + } + + @Override + public BackendEntry next() { + this.consumed++; + return this.source.next(); + } + + @Override + public void close() { + this.closes++; + } + + @Override + public Object metadata(String meta, Object... args) { + return this.consumed; + } + } + + private static final class OlapSession extends ScanRecordingSession { + private final Map values = new HashMap<>(); + private final List owners = new ArrayList<>(); + private final List> requested = new ArrayList<>(); + private int batchCalls; + private int batchCloses; + private boolean failBatch; + private int failBatchAt; + + @Override + public void put(String table, byte[] owner, byte[] key, byte[] value) { + this.owners.add(owner); + this.values.put(ByteBuffer.wrap(key), value); + } + + @Override + public byte[] get(String table, byte[] owner, byte[] key) { + this.owners.add(owner); + return this.values.get(ByteBuffer.wrap(key)); + } + + @Override + public void delete(String table, byte[] owner, byte[] key) { + this.values.remove(ByteBuffer.wrap(key)); + } + + @Override + public BackendColumnIterator getWithBatchExact(String table, List keys) { + this.batchCalls++; + this.requested.add(keys); + Iterator result = keys.stream().filter(key -> + this.values.containsKey(ByteBuffer.wrap(key.getKey()))) + .map(key -> BackendColumn.of(key.getKey(), this.values.get(ByteBuffer.wrap(key.getKey())))) + .iterator(); + return new BackendColumnIterator() { + @Override + public boolean hasNext() { + if (failBatch || (failBatchAt > 0 && batchCalls == failBatchAt)) { + throw new IllegalStateException("batch failed"); + } + return result.hasNext(); + } + + @Override + public BackendColumn next() { + return result.next(); + } + + @Override + public byte[] position() { + return null; + } + + @Override + public void close() { + batchCloses++; + } + }; + } + } + private HstoreTable newTestTable() { HstoreTable table = new HstoreTable("hugegraph", "g+oe"); table.ownerByQueryDelegate = (type, id) -> new byte[]{0}; @@ -245,7 +604,7 @@ private static byte[] keyBytes(int key) { return bytes; } - private static final class ScanRecordingSession extends HstoreSessions.Session { + private static class ScanRecordingSession extends HstoreSessions.Session { private boolean scanCalled = false; private byte[] lastQueryBytes = null; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/OpenedRocksDB.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/OpenedRocksDB.java index 2aa6d2292c..43d7cf393c 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/OpenedRocksDB.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/OpenedRocksDB.java @@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.io.FileUtils; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.rocksdb.RocksDBIteratorPool.ReusedRocksIterator; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIngester.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIngester.java index 2d379b89ea..22913895c6 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIngester.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIngester.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.util.Log; import org.rocksdb.ColumnFamilyHandle; import org.rocksdb.IngestExternalFileOptions; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIteratorPool.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIteratorPool.java index 66acdd5ec9..2923446357 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIteratorPool.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBIteratorPool.java @@ -20,7 +20,7 @@ import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.util.Log; import org.apache.hugegraph.util.StringEncoding; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStdSessions.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStdSessions.java index c1cc1c5075..467de5a273 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStdSessions.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStdSessions.java @@ -32,9 +32,9 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.serializer.BinarySerializer; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.backend.store.rocksdb.RocksDBIteratorPool.ReusedRocksIterator; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStore.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStore.java index 3b6b54eadb..eb7abcf6bc 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStore.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBStore.java @@ -44,10 +44,10 @@ import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.MergeIterator; import org.apache.hugegraph.backend.store.AbstractBackendStore; import org.apache.hugegraph.backend.store.BackendAction; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTable.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTable.java index 23e88def9b..b2082abe56 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTable.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTable.java @@ -26,23 +26,23 @@ import java.util.Set; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.backend.serializer.BinaryEntryIterator; import org.apache.hugegraph.backend.store.BackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.BackendEntryIterator; import org.apache.hugegraph.backend.store.BackendTable; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions.Session; import org.apache.hugegraph.exception.NotSupportException; import org.apache.hugegraph.iterator.FlatMapperIterator; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTables.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTables.java index becb685c58..74a52fef39 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTables.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdb/RocksDBTables.java @@ -22,10 +22,11 @@ import java.util.Collection; import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.serializer.BinarySerializer; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; @@ -234,7 +235,7 @@ public void delete(RocksDBSessions.Session session, BackendEntry entry) { * Only delete index by label will come here * Regular index delete will call eliminate() */ - for (BackendEntry.BackendColumn column : entry.columns()) { + for (BackendColumn column : entry.columns()) { // Don't assert entry.belongToMe(column), length-prefix is 1* session.deletePrefix(this.table(), column.name); } diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstSessions.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstSessions.java index b85ae5312b..052ab55387 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstSessions.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstSessions.java @@ -31,7 +31,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.rocksdb.RocksDBIngester; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions; diff --git a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstStore.java b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstStore.java index d7b75610f1..0e33cb3e50 100644 --- a/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstStore.java +++ b/hugegraph-server/hugegraph-rocksdb/src/main/java/org/apache/hugegraph/backend/store/rocksdbsst/RocksDBSstStore.java @@ -19,7 +19,7 @@ import java.util.List; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.backend.store.BackendStoreProvider; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions; import org.apache.hugegraph.backend.store.rocksdb.RocksDBStore; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java index abe4b6839c..92f9fba3e9 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; import org.apache.http.util.TextUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.util.CollectionUtil; import org.apache.hugegraph.util.JsonUtil; import org.apache.tinkerpop.shaded.jackson.core.type.TypeReference; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceAuthPayloadTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceAuthPayloadTest.java index 6333dbb44a..ca7ec157aa 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceAuthPayloadTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/auth/GraphSpaceAuthPayloadTest.java @@ -27,7 +27,7 @@ import org.apache.hugegraph.auth.HugeGroup; import org.apache.hugegraph.auth.HugePermission; import org.apache.hugegraph.auth.HugeTarget; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.junit.Test; import org.mockito.Mockito; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java index d9d36638d5..04b94cd99b 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/cypher/CypherClientTest.java @@ -22,7 +22,7 @@ import java.util.Map; import java.util.Set; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.unit.BaseUnitTest; import org.apache.tinkerpop.gremlin.process.traversal.Path; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2Test.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2Test.java index 1b05e4ee24..5d77bd25a0 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2Test.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/auth/StandardAuthManagerV2Test.java @@ -20,8 +20,8 @@ import java.util.Arrays; import java.util.Collections; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.junit.Test; import org.mockito.Mockito; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/page/QueryListTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/page/QueryListTest.java index 7fc020889b..7d49c15dc9 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/page/QueryListTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/page/QueryListTest.java @@ -24,13 +24,13 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.IdHolder.BatchIdHolder; import org.apache.hugegraph.backend.page.IdHolder.FixedIdHolder; import org.apache.hugegraph.backend.page.IdHolder.PagingIdHolder; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.QueryBatch; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.serializer.TextBackendEntry; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransactionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransactionTest.java index 65940d3e3a..ed945554ac 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransactionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransactionTest.java @@ -17,12 +17,43 @@ package org.apache.hugegraph.backend.tx; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.HugeGraphParams; +import org.apache.hugegraph.analyzer.Analyzer; +import org.apache.hugegraph.backend.serializer.AbstractSerializer; +import org.apache.hugegraph.backend.store.BackendEntry; +import org.apache.hugegraph.backend.store.BackendStore; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.builder.IndexBuilder; import org.apache.hugegraph.testutil.Assert; +import org.apache.hugegraph.unit.FakeObjects; import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IdStrategy; import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.EdgeLabelType; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.WriteType; import org.junit.Test; +import org.mockito.Mockito; public class GraphIndexTransactionTest { @@ -46,4 +77,177 @@ public void testKeepBackendIndexOrderOnlyForOrderedHstoreRangeQuery() { Assert.assertTrue(GraphIndexTransaction.keepBackendIndexOrder( true, IndexType.RANGE_INT, query)); } + + @Test + public void testEngineTransactionAndStoreBuilderShareExpansionForEveryIndexKind() { + FakeObjects objects = new FakeObjects(); + HugeGraph graph = objects.graph(); + PropertyKey text = objects.newPropertyKey(IdGenerator.of(1), "text", DataType.TEXT); + PropertyKey number = objects.newPropertyKey(IdGenerator.of(2), "number", DataType.INT); + VertexLabel vertexLabel = objects.newVertexLabel(IdGenerator.of(4), "vertex", + IdStrategy.CUSTOMIZE_NUMBER, text.id(), number.id()); + HugeVertex vertex = new HugeVertex(graph, IdGenerator.of(1), vertexLabel); + vertex.addProperty(text, "alpha beta"); + vertex.addProperty(number, 7); + vertex.expiredTime(123L); + Analyzer analyzer = value -> Set.of("alpha", "beta"); + int value = 10; + for (IndexType type : List.of(IndexType.SECONDARY, IndexType.SEARCH, IndexType.SHARD, + IndexType.UNIQUE, IndexType.RANGE_INT, IndexType.RANGE_FLOAT, + IndexType.RANGE_LONG, IndexType.RANGE_DOUBLE)) { + PropertyKey field = type.isRange() ? number : text; + IndexLabel label = objects.newIndexLabel(IdGenerator.of(value++), type.name(), + HugeType.VERTEX_LABEL, vertexLabel.id(), type, field.id()); + List expected = new IndexBuilder(graph, analyzer).buildIndex(vertex.element(), label); + List actual = captureEngineExpansion(objects, vertex, label, analyzer); + Assert.assertEquals(type.name(), expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { + Assert.assertEquals(type.name(), expected.get(i).fieldValues(), actual.get(i).fieldValues()); + Assert.assertEquals(vertex.id(), actual.get(i).elementId()); + Assert.assertEquals(123L, actual.get(i).expiredTime()); + } + if (type == IndexType.SEARCH) { + Set values = new HashSet<>(); + actual.forEach(index -> values.add(index.fieldValues())); + Assert.assertEquals(Set.of("alpha", "beta", "alpha beta"), values); + } + } + } + + @Test + public void testEngineNullableCompositePrefixAndCollectionExpansionRemainUnloaded() { + FakeObjects objects = new FakeObjects(); + PropertyKey first = objects.newPropertyKey(IdGenerator.of(1), "first", DataType.TEXT); + PropertyKey missing = objects.newPropertyKey(IdGenerator.of(2), "missing", DataType.TEXT); + PropertyKey last = objects.newPropertyKey(IdGenerator.of(3), "last", DataType.TEXT); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(4), "vertex", IdStrategy.CUSTOMIZE_NUMBER, + first.id(), missing.id(), last.id()); + label.nullableKeys(missing.id()); + HugeVertex vertex = new HugeVertex(objects.graph(), IdGenerator.of(1), label); + vertex.addProperty(first, "first"); + vertex.addProperty(last, "last"); + vertex.propNotLoaded(); + IndexLabel index = objects.newIndexLabel(IdGenerator.of(5), "composite", HugeType.VERTEX_LABEL, + label.id(), IndexType.SECONDARY, + first.id(), missing.id(), last.id()); + List actual = captureEngineExpansion(objects, vertex, index, text -> Set.of(text)); + Assert.assertEquals(1, actual.size()); + Assert.assertEquals("first", actual.get(0).fieldValues()); + Assert.assertFalse(vertex.isPropLoaded()); + + PropertyKey list = objects.newPropertyKey(IdGenerator.of(6), "list", DataType.INT, Cardinality.LIST); + label.properties(list.id()); + vertex.addProperty(list, List.of(7, -1, 7)); + IndexLabel collection = objects.newIndexLabel(IdGenerator.of(7), "collection", HugeType.VERTEX_LABEL, + label.id(), IndexType.SECONDARY, list.id()); + actual = captureEngineExpansion(objects, vertex, collection, text -> Set.of(text)); + Assert.assertEquals(3, actual.size()); + Assert.assertEquals(actual.get(0).fieldValues(), actual.get(2).fieldValues()); + } + + @Test + public void testEngineAndStoreSelectInheritedEdgeIndexesThroughSharedHelper() { + FakeObjects objects = new FakeObjects(); + PropertyKey inherited = objects.newPropertyKey(IdGenerator.of(1), "inherited", DataType.TEXT); + PropertyKey own = objects.newPropertyKey(IdGenerator.of(2), "own", DataType.TEXT); + EdgeLabel parent = objects.newEdgeLabel(IdGenerator.of(3), "parent", Frequency.MULTIPLE, + IdGenerator.of(5), IdGenerator.of(5), inherited.id()); + EdgeLabel child = objects.newEdgeLabel(IdGenerator.of(4), "child", Frequency.MULTIPLE, + IdGenerator.of(5), IdGenerator.of(5), inherited.id(), own.id()); + child.edgeLabelType(EdgeLabelType.SUB); + child.fatherId(parent.id()); + parent.enableLabelIndex(false); + child.enableLabelIndex(false); + IndexLabel parentIndex = objects.newIndexLabel(IdGenerator.of(11), "parentIndex", HugeType.EDGE_LABEL, + parent.id(), IndexType.SECONDARY, inherited.id()); + IndexLabel childIndex = objects.newIndexLabel(IdGenerator.of(12), "childIndex", HugeType.EDGE_LABEL, + child.id(), IndexType.SECONDARY, own.id()); + parent.indexLabels(parentIndex.id()); + child.indexLabels(childIndex.id()); + HugeEdge edge = new HugeEdge(objects.graph(), new EdgeId(IdGenerator.of(1), Directions.OUT, + parent.id(), child.id(), "", IdGenerator.of(2)), child); + edge.addProperty(inherited, "parent value"); + edge.addProperty(own, "child value"); + Analyzer analyzer = text -> Set.of(text); + List store = new IndexBuilder(objects.graph(), analyzer).buildEdgeIndex(edge.element()); + List engine = captureEngineIndexes(objects, List.of(parentIndex, childIndex), analyzer, + tx -> tx.updateEdgeIndex(edge, true)); + Assert.assertEquals(2, engine.size()); + Assert.assertEquals(childIndex.id(), engine.get(0).indexLabelId()); + Assert.assertEquals(parentIndex.id(), engine.get(1).indexLabelId()); + for (int i = 0; i < engine.size(); i++) { + Assert.assertEquals(store.get(i).indexLabelId(), engine.get(i).indexLabelId()); + Assert.assertEquals(store.get(i).fieldValues(), engine.get(i).fieldValues()); + } + } + + @Test + public void testEngineOlapAdapterSelectsTransactionCandidatesAndPreservesSingletonGuard() { + FakeObjects objects = new FakeObjects(); + PropertyKey property = objects.newPropertyKey(IdGenerator.of(1), "olap", DataType.INT); + property.writeType(WriteType.OLAP_COMMON); + PropertyKey unrelated = objects.newPropertyKey(IdGenerator.of(2), "other", DataType.INT); + HugeVertex vertex = new HugeVertex(objects.graph(), IdGenerator.of(1), VertexLabel.OLAP_VL); + vertex.addProperty(property, 42); + IndexLabel selected = objects.newIndexLabel(IdGenerator.of(11), "selected", HugeType.VERTEX_LABEL, + VertexLabel.OLAP_VL.id(), IndexType.RANGE_INT, property.id()); + IndexLabel other = objects.newIndexLabel(IdGenerator.of(12), "other", HugeType.VERTEX_LABEL, + VertexLabel.OLAP_VL.id(), IndexType.RANGE_INT, unrelated.id()); + List actual = captureEngineIndexes(objects, List.of(other, selected), text -> Set.of(text), + tx -> tx.updateVertexIndex(vertex, true)); + Assert.assertEquals(1, actual.size()); + Assert.assertEquals(selected.id(), actual.get(0).indexLabelId()); + Assert.assertEquals(42, actual.get(0).fieldValues()); + for (HugeVertex malformed : List.of(new HugeVertex(objects.graph(), IdGenerator.of(2), VertexLabel.OLAP_VL), + new HugeVertex(objects.graph(), IdGenerator.of(3), VertexLabel.OLAP_VL))) { + if (malformed.id().equals(IdGenerator.of(3))) { + malformed.addProperty(property, 42); + malformed.addProperty(unrelated, 43); + } + try { + captureEngineIndexes(objects, List.of(selected), text -> Set.of(text), + tx -> tx.updateVertexIndex(malformed, true)); + Assert.fail("Malformed olap vertex must fail the shared singleton guard"); + } catch (IllegalArgumentException expected) { + Assert.assertTrue(expected.getMessage().contains("Expect only 1 property")); + } + } + } + + private static List captureEngineExpansion(FakeObjects objects, HugeVertex vertex, + IndexLabel label, Analyzer analyzer) { + return captureEngineIndexes(objects, List.of(label), analyzer, + tx -> tx.updateIndex(label.id(), vertex, true)); + } + + private static List captureEngineIndexes(FakeObjects objects, List labels, + Analyzer analyzer, Consumer action) { + HugeGraphParams params = Mockito.mock(HugeGraphParams.class); + ISchemaTransaction schema = Mockito.mock(ISchemaTransaction.class); + AbstractSerializer serializer = Mockito.mock(AbstractSerializer.class); + BackendStore store = Mockito.mock(BackendStore.class); + Mockito.when(params.graph()).thenReturn(objects.graph()); + Mockito.doReturn(objects.graph().configuration()).when(params).configuration(); + Mockito.when(params.serializer()).thenReturn(serializer); + Mockito.when(params.schemaTransaction()).thenReturn(schema); + Mockito.when(schema.getIndexLabels()).thenReturn(labels); + Mockito.when(params.analyzer()).thenReturn(analyzer); + for (IndexLabel label : labels) { + Mockito.when(schema.getIndexLabel(label.id())).thenReturn(label); + } + List indexes = new ArrayList<>(); + Mockito.when(serializer.writeIndex(Mockito.any(Index.class))).thenAnswer(call -> { + indexes.add(call.getArgument(0)); + return Mockito.mock(BackendEntry.class); + }); + GraphIndexTransaction tx = new GraphIndexTransaction(params, store) { + @Override + public void doEliminate(BackendEntry entry) { + // Capture pure expansion without touching a real backend. + } + }; + action.accept(tx); + return indexes; + } + } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java index 3cb79e3687..a41ee5ffc0 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/backend/tx/GraphTransactionTest.java @@ -26,16 +26,16 @@ import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.backend.cache.Cache; import org.apache.hugegraph.backend.cache.CachedGraphTransaction; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; import org.apache.hugegraph.backend.query.QueryResultContext; import org.apache.hugegraph.backend.tx.GraphIndexTransaction.RemoveLeftIndexJob; import org.apache.hugegraph.job.EphemeralJob; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java index aa4ac8cce7..12afccd1f8 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java @@ -27,9 +27,10 @@ import javax.security.sasl.AuthenticationException; import org.apache.commons.collections.CollectionUtils; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; +import org.apache.hugegraph.auth.AuthConstant; import org.apache.hugegraph.auth.AuthManager; import org.apache.hugegraph.auth.HugeAccess; import org.apache.hugegraph.auth.HugeBelong; @@ -41,11 +42,12 @@ import org.apache.hugegraph.auth.HugeUser; import org.apache.hugegraph.auth.RolePermission; import org.apache.hugegraph.auth.StandardAuthManager; +import org.apache.hugegraph.auth.TokenGenerator; import org.apache.hugegraph.auth.UserWithRole; import org.apache.hugegraph.backend.cache.Cache; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.util.JsonUtil; @@ -1667,6 +1669,25 @@ public void testValidateUserByToken() throws AuthenticationException { Assert.assertNull(userWithRole.role()); } + @Test + public void testRejectInvalidAndExpiredTokens() { + AuthManager authManager = graph().authManager(); + TokenGenerator generator = Whitebox.getInternalState(authManager, + "tokenGenerator"); + Map claims = ImmutableMap.of(AuthConstant.TOKEN_USER_NAME, + "test"); + String expired = generator.create(claims, -60000L); + String wrongKey = new TokenGenerator("abcdefghijklmnopqrstuvwxyz012345") + .create(claims, 60000L); + + for (String token : ImmutableList.of(expired, wrongKey, "123.ansfaf")) { + UserWithRole rejected = authManager.validateUser(token); + Assert.assertEquals("", rejected.username()); + Assert.assertNull(rejected.userId()); + Assert.assertNull(rejected.role()); + } + } + @Test public void testLogout() throws AuthenticationException { AuthManager authManager = graph().authManager(); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/BaseCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/BaseCoreTest.java index 701065fe44..ab84a393d6 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/BaseCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/BaseCoreTest.java @@ -24,7 +24,7 @@ import org.apache.hugegraph.HugeGraphParams; import org.apache.hugegraph.backend.cache.CacheManager; import org.apache.hugegraph.backend.store.BackendFeatures; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java index 4ebb39dd06..273688a5c4 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CountStrategyCoreTest.java @@ -30,12 +30,12 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.query.Aggregate; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.exception.NoIndexException; import org.apache.hugegraph.schema.SchemaManager; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java index 9ea6b0e919..d626df4a1a 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeCoreTest.java @@ -30,24 +30,24 @@ import java.util.concurrent.ExecutionException; import java.util.function.Function; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.PageInfo; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendTable; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.LimitExceedException; import org.apache.hugegraph.exception.NoIndexException; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; @@ -3176,9 +3176,7 @@ public void testQueryAdjacentVerticesOfEdges() { // Fill edge properties Assert.assertEquals(2, edge.getProperties().size()); - Whitebox.setInternalState(edge, "propLoaded", false); - Whitebox.setInternalState(edge, "properties", - CollectionFactory.newIntObjectMap()); + edge.resetProperties(); Assert.assertEquals(0, edge.getProperties().size()); Assert.assertEquals(2, edge.getFilledProperties().size()); Assert.assertEquals(2, edge.getProperties().size()); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java index 8629f78b3e..f490641f7c 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java @@ -20,15 +20,15 @@ import java.util.Date; import java.util.List; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NoIndexException; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.Frequency; import org.apache.hugegraph.util.DateUtil; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/IndexLabelCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/IndexLabelCoreTest.java index 24a905427c..c9988db513 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/IndexLabelCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/IndexLabelCoreTest.java @@ -20,16 +20,16 @@ import java.util.Date; import java.util.List; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NoIndexException; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.IndexType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/MultiGraphsTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/MultiGraphsTest.java index bb45b47e3b..1064d3a0fd 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/MultiGraphsTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/MultiGraphsTest.java @@ -26,19 +26,19 @@ import org.apache.commons.configuration2.BaseConfiguration; import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.PropertiesConfiguration; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.BackendStoreInfo; import org.apache.hugegraph.backend.store.rocksdb.RocksDBOptions; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.masterelection.GlobalMasterInfo; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Utils; import org.apache.tinkerpop.gremlin.structure.T; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/ParentAndSubEdgeCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/ParentAndSubEdgeCoreTest.java index 4d7cc3eea3..b657b62c57 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/ParentAndSubEdgeCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/ParentAndSubEdgeCoreTest.java @@ -21,7 +21,7 @@ import java.util.List; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.testutil.Assert; import org.apache.tinkerpop.gremlin.structure.Edge; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyCoreTest.java index 873efd5e84..755380fc8b 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyCoreTest.java @@ -26,7 +26,7 @@ import java.util.UUID; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Utils; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyKeyCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyKeyCoreTest.java index 0609f607ba..240b4d86f7 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyKeyCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/PropertyKeyCoreTest.java @@ -19,13 +19,13 @@ import java.util.Date; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.AggregateType; import org.apache.hugegraph.type.define.Cardinality; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/RamTableTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/RamTableTest.java index 8a1f6c4910..359505d945 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/RamTableTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/RamTableTest.java @@ -24,9 +24,9 @@ import org.apache.commons.io.FileUtils; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.store.ram.RamTable; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.schema.SchemaManager; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/SchemaCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/SchemaCoreTest.java index 0d70bb203b..b459224706 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/SchemaCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/SchemaCoreTest.java @@ -22,12 +22,12 @@ import java.util.List; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java index 9e82692689..82069eca30 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java @@ -28,11 +28,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.api.job.GremlinAPI.GremlinRequest; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.job.EphemeralJob; import org.apache.hugegraph.job.EphemeralJobBuilder; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java index 16cc7d0c83..b6657ae150 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexCoreTest.java @@ -33,30 +33,30 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.cache.CachedGraphTransaction; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.Id.IdType; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.id.SnowflakeIdGenerator; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; +import org.apache.hugegraph.id.SplicingIdGenerator; import org.apache.hugegraph.backend.page.PageInfo; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendTable; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.backend.tx.GraphTransaction; import org.apache.hugegraph.exception.LimitExceedException; import org.apache.hugegraph.exception.NoIndexException; import org.apache.hugegraph.exception.NotAllowException; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.FakeObjects; @@ -7872,7 +7872,7 @@ public void testScanVertexInPaging() { Iterator iterator = graph.vertices(query); while (iterator.hasNext()) { Vertex vertex = iterator.next(); - Assert.assertTrue(query.test((HugeElement) vertex)); + Assert.assertTrue(query.test(((HugeElement) vertex).element())); vertices.add(vertex); } page = PageInfo.pageInfo(iterator); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java index a43731f235..e25c0aa0d4 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java @@ -20,16 +20,16 @@ import java.util.Date; import java.util.List; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.exception.ExistedException; import org.apache.hugegraph.exception.NoIndexException; import org.apache.hugegraph.exception.NotFoundException; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.task.HugeTask; import org.apache.hugegraph.task.TaskScheduler; import org.apache.hugegraph.task.TaskStatus; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index b3a83d0e50..a059ce5848 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -26,11 +26,11 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; import org.apache.hugegraph.backend.cache.CachedBackendStore; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.backend.BinaryId; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.dist.RegisterUtil; import org.apache.hugegraph.masterelection.GlobalMasterInfo; @@ -38,8 +38,8 @@ import org.apache.hugegraph.memory.consumer.factory.IdFactory; import org.apache.hugegraph.memory.consumer.factory.PropertyFactory; import org.apache.hugegraph.memory.consumer.impl.id.StringIdOffHeap; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; @@ -143,7 +143,7 @@ public void testBinaryId() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); Id idOffHeap = IdFactory.getInstance().newBinaryId(stringIdOffHeap.asBytes(), stringIdOffHeap); - Id id = new BinaryBackendEntry.BinaryId(stringIdOffHeap.asBytes(), stringIdOffHeap); + Id id = new BinaryId(stringIdOffHeap.asBytes(), stringIdOffHeap); Assert.assertNotNull(idOffHeap); Assert.assertArrayEquals(stringIdOffHeap.asBytes(), idOffHeap.asBytes()); Assert.assertEquals(id, ((OffHeapObject) idOffHeap).zeroCopyReadFromByteBuf()); @@ -180,20 +180,49 @@ public void testEdgeId() { Id edgeLabelIdOffHeap = IdFactory.getInstance().newLongId(1); Id subLabelIdOffHeap = IdFactory.getInstance().newLongId(2); Id edgeIdOffHeap = - IdFactory.getInstance().newEdgeId(java, Directions.OUT, edgeLabelIdOffHeap, + IdFactory.getInstance().newEdgeId(java.id(), Directions.OUT, edgeLabelIdOffHeap, subLabelIdOffHeap, - "test", java); - Id edgeId = new EdgeId(java, + "test", java.id()); + Id edgeId = new EdgeId(java.id(), Directions.OUT, (Id) ((OffHeapObject) edgeLabelIdOffHeap).zeroCopyReadFromByteBuf(), (Id) ((OffHeapObject) subLabelIdOffHeap).zeroCopyReadFromByteBuf(), "test", - java); + java.id()); Assert.assertNotNull(edgeIdOffHeap); // TODO: adopt equals method Assert.assertEquals(edgeId.asString(), edgeIdOffHeap.asString()); } + @Test + public void testEdgeIdFormattingUsesSharedComponentsAndCache() { + Id owner = IdFactory.getInstance().newStringId("owner>vertex"); + Id other = IdFactory.getInstance().newStringId("other`vertex"); + Id label = IdFactory.getInstance().newLongId(1); + Id subLabel = IdFactory.getInstance().newLongId(2); + String[] sortValues = {"value", "a>b`c!d:北京"}; + for (Directions direction : new Directions[]{Directions.OUT, Directions.IN}) { + for (boolean directed : new boolean[]{false, true}) { + for (String sortValue : sortValues) { + EdgeId offHeap = IdFactory.getInstance().newEdgeId( + owner, direction, label, subLabel, sortValue, other, directed); + EdgeId onHeap = new EdgeId(IdGenerator.of("owner>vertex"), direction, + IdGenerator.of(1), IdGenerator.of(2), sortValue, + IdGenerator.of("other`vertex"), directed); + OffHeapObject consumer = (OffHeapObject) offHeap; + int memoryBlocks = consumer.getAllMemoryBlock().size(); + String formatted = offHeap.asString(); + Assert.assertEquals(onHeap.asString(), formatted); + Assert.assertEquals(memoryBlocks + 1, consumer.getAllMemoryBlock().size()); + Assert.assertEquals(formatted, offHeap.asString()); + Assert.assertEquals(memoryBlocks + 1, consumer.getAllMemoryBlock().size()); + Assert.assertArrayEquals(onHeap.asBytes(), offHeap.asBytes()); + Assert.assertEquals(sortValue, offHeap.sortValues()); + } + } + } + } + @Test public void testProperty() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); @@ -201,12 +230,12 @@ public void testProperty() { Id edgeLabelIdOffHeap = IdFactory.getInstance().newLongId(1); Id subLabelIdOffHeap = IdFactory.getInstance().newLongId(2); - Id edgeId = new EdgeId(java, + Id edgeId = new EdgeId(java.id(), Directions.OUT, (Id) ((OffHeapObject) edgeLabelIdOffHeap).zeroCopyReadFromByteBuf(), (Id) ((OffHeapObject) subLabelIdOffHeap).zeroCopyReadFromByteBuf(), "test", - java); + java.id()); HugeEdge testEdge = new HugeEdge(graph, edgeId, EdgeLabel.NONE); PropertyKey propertyKey = new PropertyKey(null, IdFactory.getInstance().newLongId(3), "fake"); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManagerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManagerTest.java index 074753308e..32115c050d 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManagerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/meta/managers/AuthMetaManagerTest.java @@ -20,7 +20,7 @@ import java.util.Map; import org.apache.hugegraph.auth.HugeTarget; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.meta.MetaDriver; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.util.JsonUtil; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/task/TaskAndResultSchedulerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/task/TaskAndResultSchedulerTest.java index a31c70e8d1..d45b6f5137 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/task/TaskAndResultSchedulerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/task/TaskAndResultSchedulerTest.java @@ -24,10 +24,10 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.core.BaseCoreTest; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/testutil/Utils.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/testutil/Utils.java index e081423b8e..5fd9928561 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/testutil/Utils.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/testutil/Utils.java @@ -24,10 +24,10 @@ import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.builder.fluent.Configurations; import org.apache.commons.configuration2.ex.ConfigurationException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.util.DateUtil; import org.apache.hugegraph.util.E; import org.apache.tinkerpop.gremlin.structure.Edge; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/HugeGraphTestInfrastructureTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/HugeGraphTestInfrastructureTest.java index efe2d5fba2..070bcae9a1 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/HugeGraphTestInfrastructureTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/HugeGraphTestInfrastructureTest.java @@ -23,9 +23,9 @@ import java.util.List; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.junit.Test; import org.mockito.Mockito; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/TestGraph.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/TestGraph.java index 4d76cb72bf..97447f08ac 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/TestGraph.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/TestGraph.java @@ -30,7 +30,7 @@ import org.apache.hugegraph.io.HugeGraphSONModule; import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.task.TaskScheduler; import org.apache.hugegraph.testutil.Whitebox; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtilOptimizeTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtilOptimizeTest.java index 630c08dbfb..54a49c67aa 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtilOptimizeTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtilOptimizeTest.java @@ -25,10 +25,10 @@ import java.util.Set; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.DataType; import org.apache.tinkerpop.gremlin.process.traversal.GType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/BaseUnitTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/BaseUnitTest.java index b6dc0bf96a..5be6c3a5e0 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/BaseUnitTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/BaseUnitTest.java @@ -26,7 +26,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.util.Log; import org.apache.hugegraph.util.TimeUtil; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/FakeObjects.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/FakeObjects.java index 9dabd72a3a..e4bd85f578 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/FakeObjects.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/FakeObjects.java @@ -22,17 +22,17 @@ import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.config.TypedOption; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; -import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; @@ -53,6 +53,10 @@ public FakeObjects(String name) { public FakeObjects() { this.graph = Mockito.mock(HugeGraph.class); Mockito.doReturn(newConfig()).when(this.graph).configuration(); + Mockito.doAnswer(invocation -> { + TypedOption option = invocation.getArgument(0); + return this.graph.configuration().get(option); + }).when(this.graph).option(Mockito.any()); Mockito.doReturn(true).when(this.graph).sameAs(this.graph); } @@ -159,8 +163,7 @@ public HugeEdge newEdge(long sourceVertexId, long targetVertexId) { Id id = EdgeId.parse("L123456>1>1>>L987654"); HugeEdge edge = new HugeEdge(this.graph(), id, el); - Whitebox.setInternalState(edge, "sourceVertex", source); - Whitebox.setInternalState(edge, "targetVertex", target); + edge.vertices(true, source, target); edge.assignId(); edge.addProperty(date, new Date()); edge.addProperty(weight, 0.75); @@ -202,8 +205,7 @@ public HugeEdge newEdge(String sourceVertexId, String targetVertexId) { Id id = EdgeId.parse("L123456>1>1>>L987654"); HugeEdge edge = new HugeEdge(this.graph(), id, el); - Whitebox.setInternalState(edge, "sourceVertex", source); - Whitebox.setInternalState(edge, "targetVertex", target); + edge.vertices(true, source, target); edge.assignId(); edge.addProperty(date, new Date()); edge.addProperty(weight, 0.75); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java index f772ffd927..617440b668 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java @@ -65,6 +65,8 @@ import org.apache.hugegraph.unit.core.GroovyScriptEngineCompatibilityTest; import org.apache.hugegraph.unit.core.HugeFeaturesTest; import org.apache.hugegraph.unit.core.HstoreSessionsTest; +import org.apache.hugegraph.unit.core.HugeElementViewTest; +import org.apache.hugegraph.unit.core.HugePrimaryKeyTest; import org.apache.hugegraph.unit.core.IdHolderTest; import org.apache.hugegraph.unit.core.LocksTableTest; import org.apache.hugegraph.unit.core.PageStateTest; @@ -198,6 +200,8 @@ HugeGraphAuthProxyTest.class, SchemaElementTest.class, HugeGraphTestInfrastructureTest.class, + HugeElementViewTest.class, + HugePrimaryKeyTest.class, ShortestPathTraverserTest.class, /* cmd */ diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/auth/HugeGraphAuthProxyTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/auth/HugeGraphAuthProxyTest.java index 60d2e097eb..e5b8494945 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/auth/HugeGraphAuthProxyTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/auth/HugeGraphAuthProxyTest.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.auth.AuthManager; import org.apache.hugegraph.auth.HugeAuthenticator; @@ -34,8 +34,8 @@ import org.apache.hugegraph.auth.RolePermission; import org.apache.hugegraph.auth.UserWithRole; import org.apache.hugegraph.backend.cache.Cache; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.AuthOptions; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.task.TaskManager; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheManagerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheManagerTest.java index 8d7ef2166a..034bbf46a8 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheManagerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheManagerTest.java @@ -26,8 +26,8 @@ import org.apache.hugegraph.backend.cache.CacheManager; import org.apache.hugegraph.backend.cache.OffheapCache; import org.apache.hugegraph.backend.cache.RamCache; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.unit.BaseUnitTest; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheTest.java index d9bd4cf953..8883bcf3b4 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CacheTest.java @@ -29,8 +29,8 @@ import org.apache.hugegraph.backend.cache.LevelCache; import org.apache.hugegraph.backend.cache.OffheapCache; import org.apache.hugegraph.backend.cache.RamCache; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.unit.BaseUnitTest; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java index ae0321ee01..8708d78479 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedGraphTransactionTest.java @@ -36,14 +36,14 @@ import org.apache.hugegraph.backend.cache.CachedBackendStore.QueryId; import org.apache.hugegraph.backend.cache.CachedGraphTransaction; import org.apache.hugegraph.backend.cache.OffheapCache; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery.OptimizedType; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery.OptimizedType; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResultContext; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendStore; @@ -51,7 +51,7 @@ import org.apache.hugegraph.backend.store.ram.RamTable; import org.apache.hugegraph.event.EventHub; import org.apache.hugegraph.event.EventListener; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedSchemaTransactionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedSchemaTransactionTest.java index 9e7aec3842..a4ea489817 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedSchemaTransactionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/CachedSchemaTransactionTest.java @@ -39,14 +39,14 @@ import org.apache.hugegraph.backend.cache.CacheManager; import org.apache.hugegraph.backend.cache.CachedSchemaTransaction; import org.apache.hugegraph.backend.cache.CachedSchemaTransactionV2; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.event.EventHub; import org.apache.hugegraph.event.EventListener; import org.apache.hugegraph.meta.MetaDriver; import org.apache.hugegraph.meta.MetaManager; import org.apache.hugegraph.meta.managers.GraphMetaManager; -import org.apache.hugegraph.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/RamTableTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/RamTableTest.java index 245f311bcb..c7bbfd874f 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/RamTableTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cache/RamTableTest.java @@ -19,14 +19,14 @@ import java.util.Iterator; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.ram.RamTable; -import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GraphBinarySchemaCompatibilityTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GraphBinarySchemaCompatibilityTest.java index 60fd0cfe96..f8b1d704c7 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GraphBinarySchemaCompatibilityTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GraphBinarySchemaCompatibilityTest.java @@ -22,15 +22,15 @@ import java.util.Map; import java.util.UUID; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.backend.tx.ISchemaTransaction; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.io.HugeGraphTypeSerializerRegistryBuilder; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GremlinConfigCompatibilityTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GremlinConfigCompatibilityTest.java index 1ab85c8905..d66a5aca8c 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GremlinConfigCompatibilityTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/config/GremlinConfigCompatibilityTest.java @@ -40,11 +40,11 @@ import java.util.regex.Pattern; import java.util.stream.Stream; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.io.HugeGraphIoRegistry; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeFeatures; import org.apache.hugegraph.structure.HugeVertex; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendMutationTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendMutationTest.java index e07727fd23..728fc7fb1e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendMutationTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendMutationTest.java @@ -19,9 +19,9 @@ import java.util.List; -import org.apache.hugegraph.HugeException; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.SplicingIdGenerator; import org.apache.hugegraph.backend.serializer.TextBackendEntry; import org.apache.hugegraph.backend.store.BackendAction; import org.apache.hugegraph.backend.store.BackendEntry; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendProviderFactoryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendProviderFactoryTest.java index 767febd620..58bd977b6e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendProviderFactoryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/BackendProviderFactoryTest.java @@ -25,7 +25,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.store.BackendProviderFactory; import org.apache.hugegraph.backend.store.memory.InMemoryDBStoreProvider; import org.apache.hugegraph.backend.store.raft.RaftBackendStoreProvider; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionQueryFlattenTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionQueryFlattenTest.java index 64833a3f70..0d9c2187a2 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionQueryFlattenTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionQueryFlattenTest.java @@ -21,10 +21,10 @@ import java.util.Collection; import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.backend.query.ConditionQueryFlatten; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionTest.java index bd376d495d..0305fa1bf5 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ConditionTest.java @@ -19,11 +19,11 @@ import java.util.Date; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.Condition.Relation; -import org.apache.hugegraph.backend.query.Condition.RelationType; -import org.apache.hugegraph.backend.query.Condition.SyspropRelation; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.Condition.Relation; +import org.apache.hugegraph.query.Condition.RelationType; +import org.apache.hugegraph.query.Condition.SyspropRelation; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.traversal.optimize.ConditionP; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/DirectionsTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/DirectionsTest.java index 0f6b69e8fc..75678b82cc 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/DirectionsTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/DirectionsTest.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.unit.core; +import org.apache.hugegraph.util.TinkerPopUtil; + import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Directions; @@ -59,16 +61,16 @@ public void testOpposite() { @Test public void testToDirection() { - Assert.assertEquals(Direction.OUT, Directions.OUT.direction()); - Assert.assertEquals(Direction.IN, Directions.IN.direction()); - Assert.assertEquals(Direction.BOTH, Directions.BOTH.direction()); + Assert.assertEquals(Direction.OUT, TinkerPopUtil.direction(Directions.OUT)); + Assert.assertEquals(Direction.IN, TinkerPopUtil.direction(Directions.IN)); + Assert.assertEquals(Direction.BOTH, TinkerPopUtil.direction(Directions.BOTH)); } @Test public void testFromDirection() { - Assert.assertEquals(Directions.OUT, Directions.convert(Direction.OUT)); - Assert.assertEquals(Directions.IN, Directions.convert(Direction.IN)); + Assert.assertEquals(Directions.OUT, TinkerPopUtil.direction(Direction.OUT)); + Assert.assertEquals(Directions.IN, TinkerPopUtil.direction(Direction.IN)); Assert.assertEquals(Directions.BOTH, - Directions.convert(Direction.BOTH)); + TinkerPopUtil.direction(Direction.BOTH)); } } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerAdminInitTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerAdminInitTest.java index 60e59666f4..490ffb9920 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerAdminInitTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerAdminInitTest.java @@ -22,7 +22,7 @@ import java.util.Map; import org.apache.commons.configuration2.PropertiesConfiguration; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.auth.HugeAuthenticator; import org.apache.hugegraph.auth.HugeUser; import org.apache.hugegraph.auth.StandardAuthenticator; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerStoresWaitTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerStoresWaitTest.java index c9d991cee0..e5e060e2d3 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerStoresWaitTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/GraphManagerStoresWaitTest.java @@ -30,7 +30,7 @@ import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.core.GraphManager.Readiness; import org.apache.hugegraph.pd.client.PDConfig; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugeElementViewTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugeElementViewTest.java new file mode 100644 index 0000000000..1255ac5754 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugeElementViewTest.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.unit.core; + +import java.util.Collection; +import java.util.Iterator; + +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.BaseEdge; +import org.apache.hugegraph.structure.BaseProperty; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.HugeProperty; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.structure.HugeVertexProperty; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.IdStrategy; +import org.apache.hugegraph.unit.FakeObjects; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class HugeElementViewTest { + + @Test + public void testPropertyViewWrapsOnlyConsumedEntries() { + FakeObjects objects = new FakeObjects(); + PropertyKey name = objects.newPropertyKey(IdGenerator.of(1), "name"); + PropertyKey city = objects.newPropertyKey(IdGenerator.of(2), "city"); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", + IdStrategy.CUSTOMIZE_NUMBER, + name.id(), city.id()); + CountingVertex vertex = new CountingVertex(objects.graph(), label); + vertex.addProperty(name, "tom"); + vertex.wrapped = 0; + + Collection> properties = vertex.getProperties(); + Assert.assertEquals(1, properties.size()); + Assert.assertEquals(0, vertex.wrapped); + Iterator> iterator = properties.iterator(); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(0, vertex.wrapped); + Assert.assertEquals("tom", iterator.next().value()); + Assert.assertEquals(1, vertex.wrapped); + + vertex.addProperty(city, "Beijing"); + vertex.wrapped = 0; + Assert.assertEquals(2, properties.size()); + Assert.assertEquals(0, vertex.wrapped); + properties.clear(); + Assert.assertEquals(0, vertex.sizeOfProperties()); + Assert.assertEquals(0, vertex.wrapped); + } + + @Test + public void testPropertyViewIteratorRemovesSharedEntry() { + FakeObjects objects = new FakeObjects(); + PropertyKey name = objects.newPropertyKey(IdGenerator.of(1), "name"); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", + IdStrategy.CUSTOMIZE_NUMBER, name.id()); + CountingVertex vertex = new CountingVertex(objects.graph(), label); + vertex.addProperty(name, "tom"); + Iterator> iterator = vertex.getProperties().iterator(); + iterator.next(); + iterator.remove(); + Assert.assertFalse(vertex.hasProperty(name.id())); + Assert.assertFalse(vertex.element().hasProperty(name.id())); + } + + @Test + public void testFreshEngineStateViewsDoNotShareMutableEmptyProperties() { + FakeObjects objects = new FakeObjects(); + PropertyKey key = objects.newPropertyKey(IdGenerator.of(1), "name"); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", + IdStrategy.CUSTOMIZE_NUMBER, key.id()); + CountingVertex first = new CountingVertex(objects.graph(), label); + CountingVertex second = new CountingVertex(objects.graph(), label); + Collection> secondView = second.getProperties(); + Assert.assertEquals(0, secondView.size()); + Assert.assertFalse(secondView.iterator().hasNext()); + Assert.assertEquals(0, second.wrapped); + first.element().properties().put(1, new BaseProperty<>(key, "first")); + Assert.assertEquals("first", first.getPropertyValue(key.id())); + Assert.assertTrue(secondView.isEmpty()); + secondView.clear(); + Assert.assertEquals("first", first.getPropertyValue(key.id())); + Assert.assertEquals(0, second.wrapped); + } + + @Test + public void testAdoptedAdjacencyPreservesOwnerStateAndStableWrappers() { + FakeObjects objects = new FakeObjects(); + PropertyKey name = objects.newPropertyKey(IdGenerator.of(1), "name"); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", + IdStrategy.CUSTOMIZE_NUMBER, name.id()); + EdgeLabel link = objects.newEdgeLabel(IdGenerator.of(2), "link", Frequency.SINGLE, + label.id(), label.id()); + for (boolean out : new boolean[]{true, false}) { + BaseVertex owner = new BaseVertex(IdGenerator.of(1), label); + owner.addProperty(name, "tom"); + BaseEdge base = BaseEdge.constructEdge(objects.graph(), owner, out, link, "", IdGenerator.of(2)); + base.expiredTime(123); + HugeVertex vertex = new HugeVertex(objects.graph(), owner); + Assert.assertEquals(1, vertex.getEdges().size()); + HugeEdge edge = vertex.getEdges().iterator().next(); + Assert.assertSame(vertex, edge.ownerVertex()); + Assert.assertSame(base, edge.element()); + Assert.assertSame(owner.getProperty(name.id()), vertex.getProperty(name.id()).baseProperty()); + Assert.assertSame(edge, vertex.getEdges().iterator().next()); + Assert.assertEquals(out, edge.element().isOutEdge()); + Assert.assertEquals(123, edge.expiredTime()); + Assert.assertFalse(vertex.isPropLoaded()); + vertex.removeEdge(edge); + Assert.assertTrue(owner.edges().isEmpty()); + } + } + + @Test + public void testCanonicalSelfLoopAndCopyResetKeepMembershipConsistent() { + FakeObjects objects = new FakeObjects(); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", IdStrategy.CUSTOMIZE_NUMBER); + EdgeLabel link = objects.newEdgeLabel(IdGenerator.of(2), "link", Frequency.SINGLE, + label.id(), label.id()); + BaseVertex base = new BaseVertex(IdGenerator.of(1), label); + BaseEdge loop = new BaseEdge(link, true); + loop.vertices(true, base, base); + loop.name(""); + loop.assignId(); + base.addEdge(loop); + HugeVertex vertex = new HugeVertex(objects.graph(), base); + HugeEdge edge = vertex.getEdges().iterator().next(); + Assert.assertTrue(edge.selfLoop()); + Assert.assertSame(vertex, edge.sourceVertex()); + Assert.assertSame(vertex, edge.targetVertex()); + Assert.assertSame(vertex, edge.switchOwner().ownerVertex()); + HugeVertex copy = vertex.copy(); + copy.resetEdges(); + Assert.assertTrue(copy.getEdges().isEmpty()); + Assert.assertEquals(1, vertex.getEdges().size()); + Assert.assertEquals(1, base.edges().size()); + } + + @Test + public void testConstructedEdgeUsesOneAdjacencyMembershipAndOriginalOwner() { + FakeObjects objects = new FakeObjects(); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", IdStrategy.CUSTOMIZE_NUMBER); + EdgeLabel link = objects.newEdgeLabel(IdGenerator.of(2), "link", Frequency.SINGLE, + label.id(), label.id()); + HugeVertex vertex = new HugeVertex(objects.graph(), IdGenerator.of(1), label); + HugeEdge edge = HugeEdge.constructEdge(vertex, false, link, "", IdGenerator.of(2)); + Assert.assertSame(vertex, edge.ownerVertex()); + Assert.assertSame(edge, vertex.getEdges().iterator().next()); + Assert.assertEquals(1, vertex.element().edges().size()); + Assert.assertEquals(1, edge.otherVertex().element().edges().size()); + Assert.assertSame(edge.element(), vertex.element().edges().iterator().next()); + Assert.assertSame(edge.otherVertex(), edge.otherVertex().getEdges().iterator().next().ownerVertex()); + } + + @Test + public void testEdgeConstructionWithoutSchemaLookupRetainsEngineGraph() { + FakeObjects objects = new FakeObjects(); + VertexLabel label = objects.newVertexLabel(IdGenerator.of(1), "person", IdStrategy.CUSTOMIZE_NUMBER); + EdgeLabel link = objects.newEdgeLabel(IdGenerator.of(2), "link", Frequency.SINGLE, + label.id(), label.id()); + HugeVertex owner = new HugeVertex(objects.graph(), IdGenerator.of(1), label); + HugeEdge withoutLabel = HugeEdge.constructEdgeWithoutLabel(owner, true, "", IdGenerator.of(2)); + Assert.assertSame(owner, withoutLabel.ownerVertex()); + Assert.assertSame(label, owner.schemaLabel()); + Assert.assertTrue(withoutLabel.otherVertex().schemaLabel().undefined()); + Assert.assertEquals(VertexLabel.NONE.id(), withoutLabel.otherVertex().schemaLabel().id()); + Assert.assertSame(objects.graph(), withoutLabel.schemaLabel().graph()); + Assert.assertSame(objects.graph(), withoutLabel.otherVertex().schemaLabel().graph()); + Assert.assertEquals(1, owner.element().edges().size()); + + owner.resetEdges(); + HugeEdge withoutLookup = HugeEdge.constructEdgeWithoutGraph(owner, true, link, "", IdGenerator.of(2)); + Assert.assertSame(objects.graph(), withoutLookup.graph()); + Assert.assertSame(owner, withoutLookup.ownerVertex()); + Assert.assertTrue(withoutLookup.otherVertex().schemaLabel().undefined()); + Assert.assertSame(objects.graph(), withoutLookup.schemaLabel().graph()); + Assert.assertSame(objects.graph(), withoutLookup.ownerVertex().schemaLabel().graph()); + Assert.assertSame(objects.graph(), withoutLookup.otherVertex().schemaLabel().graph()); + Assert.assertEquals(1, owner.element().edges().size()); + Mockito.verify(objects.graph(), Mockito.never()).vertexLabelOrNone(Mockito.any()); + } + + private static final class CountingVertex extends HugeVertex { + + private int wrapped; + + private CountingVertex(HugeGraph graph, VertexLabel label) { + super(graph, IdGenerator.of(1), label); + } + + @Override + protected HugeVertexProperty wrapProperty(BaseProperty property) { + this.wrapped++; + return super.wrapProperty(property); + } + } +} diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugePrimaryKeyTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugePrimaryKeyTest.java new file mode 100644 index 0000000000..d567fc922b --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/HugePrimaryKeyTest.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.unit.core; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.hugegraph.backend.tx.GraphTransaction; +import org.apache.hugegraph.config.CoreOptions; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.testutil.Whitebox; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.type.define.IdStrategy; +import org.apache.hugegraph.unit.FakeObjects; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class HugePrimaryKeyTest { + + @Test + public void testEmptyPrimaryKeyStillRejected() { + Fixture fixture = new Fixture(true, ""); + IllegalArgumentException error = Assert.assertThrows(IllegalArgumentException.class, + () -> fixture.vertex.assignId(null)); + Assert.assertTrue(error.getMessage().contains("primary key can't be empty")); + } + + @Test + public void testReservedLeadingSymbolsStillRejected() { + for (char value = 0; value <= 3; value++) { + Fixture fixture = new Fixture(true, value + "value"); + IllegalArgumentException error = Assert.assertThrows(IllegalArgumentException.class, + () -> fixture.vertex.assignId(null)); + Assert.assertTrue(error.getMessage().contains("Illegal leading char")); + } + } + + @Test + public void testEnginePrimaryIdMatchesActualQueryOptimizer() { + Fixture escaped = new Fixture(true, "a!b", "left>right:tail`x"); + escaped.vertex.assignId(null); + Assert.assertEquals(escaped.vertex.id(), escaped.optimizedQueryId(false)); + Fixture numeric = new Fixture(true, 42); + numeric.vertex.assignId(null); + Assert.assertEquals(numeric.vertex.id(), numeric.optimizedQueryId(false)); + } + + @Test + public void testCompositeEmptyFieldRetainsLegacyEncodedName() { + Fixture fixture = new Fixture(true, "first", "", "a!b"); + fixture.vertex.assignId(null); + Assert.assertEquals("1:first!!a`!b", fixture.vertex.id().asString()); + Assert.assertEquals(fixture.vertex.id(), fixture.optimizedQueryId(true)); + } + + @Test + public void testNumberEncodingOptionRetainsPlainNumberMode() { + Fixture plain = new Fixture(false, 42); + plain.vertex.assignId(null); + Assert.assertEquals("1:42", plain.vertex.id().asString()); + Assert.assertEquals(plain.vertex.id(), plain.optimizedQueryId(true)); + Fixture encoded = new Fixture(true, 42); + encoded.vertex.assignId(null); + Assert.assertNotEquals(plain.vertex.id(), encoded.vertex.id()); + } + + private static final class Fixture { + + private final FakeObjects objects = new FakeObjects(); + private final List keys = new ArrayList<>(); + private final Object[] values; + private final boolean encodeNumber; + private final VertexLabel label; + private final HugeVertex vertex; + + private Fixture(boolean encodeNumber, Object... values) { + this.values = values; + this.encodeNumber = encodeNumber; + Mockito.doReturn(encodeNumber).when(this.objects.graph()).option(CoreOptions.VERTEX_ENCODE_PK_NUMBER); + for (int i = 0; i < values.length; i++) { + this.keys.add(this.objects.newPropertyKey(IdGenerator.of(i + 1), "key" + i, + values[i] instanceof Number ? DataType.INT : DataType.TEXT)); + } + Id[] ids = this.keys.stream().map(PropertyKey::id).toArray(Id[]::new); + this.label = this.objects.newVertexLabel(IdGenerator.of(1), "person", IdStrategy.PRIMARY_KEY, ids); + this.label.primaryKeys(ids); + this.vertex = new HugeVertex(this.objects.graph(), null, this.label); + for (int i = 0; i < values.length; i++) { + this.vertex.addProperty(this.keys.get(i), values[i]); + } + } + + private Id optimizedQueryId(boolean serializedValues) { + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.eq(HugeKeys.LABEL, this.label.id()); + for (int i = 0; i < this.values.length; i++) { + Condition.Relation relation = Condition.eq(this.keys.get(i).id(), this.values[i]); + if (serializedValues) { + Object value = this.keys.get(i).serialValue(this.values[i], this.encodeNumber); + relation.serialValue("".equals(value) ? ConditionQuery.INDEX_VALUE_EMPTY : value); + } + query.query(relation); + } + GraphTransaction tx = Mockito.mock(GraphTransaction.class, Mockito.CALLS_REAL_METHODS); + Mockito.doReturn(this.objects.graph()).when(tx).graph(); + Query optimized = Whitebox.invoke(GraphTransaction.class, new Class[]{ConditionQuery.class}, + "optimizeQuery", tx, query); + return optimized.ids().iterator().next(); + } + } +} diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/IdHolderTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/IdHolderTest.java index c6bdcc32d5..a4822307f5 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/IdHolderTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/IdHolderTest.java @@ -22,17 +22,17 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.IdHolder.BatchIdHolder; import org.apache.hugegraph.backend.page.IdHolder.PagingIdHolder; import org.apache.hugegraph.backend.page.IdHolderList; import org.apache.hugegraph.backend.page.PageIds; import org.apache.hugegraph.backend.page.PageState; import org.apache.hugegraph.backend.page.QueryList; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryResults; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.testutil.Assert; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/LocksTableTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/LocksTableTest.java index 00eb918211..2fded2bf6c 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/LocksTableTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/LocksTableTest.java @@ -22,8 +22,8 @@ import java.util.Set; import java.util.concurrent.locks.Lock; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.concurrent.LockManager; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/PageStateTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/PageStateTest.java index ba1b37f5c4..34f12f3a0f 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/PageStateTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/PageStateTest.java @@ -19,7 +19,7 @@ import java.util.Arrays; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.page.PageState; import org.apache.hugegraph.testutil.Assert; import org.junit.Test; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryResultsTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryResultsTest.java index 64c675f647..dc2c4f2233 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryResultsTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryResultsTest.java @@ -24,13 +24,13 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.page.PageInfo; import org.apache.hugegraph.backend.page.PageState; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.Query; import org.apache.hugegraph.backend.query.QueryBatch; import org.apache.hugegraph.backend.query.QueryResultContext; import org.apache.hugegraph.backend.query.QueryResults; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java index 5778ceba7c..622535cbc0 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/QueryTest.java @@ -17,16 +17,16 @@ package org.apache.hugegraph.unit.core; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; -import org.apache.hugegraph.backend.query.Condition; -import org.apache.hugegraph.backend.query.ConditionQuery; -import org.apache.hugegraph.backend.query.IdPrefixQuery; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.query.IdRangeQuery; -import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.backend.query.Query.Order; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.query.Query.Order; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RangeTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RangeTest.java index 39b28784b9..d016fa07ab 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RangeTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RangeTest.java @@ -20,7 +20,7 @@ import java.util.List; import org.apache.hugegraph.backend.store.BackendTable.ShardSplitter.Range; -import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.testutil.Assert; import org.apache.logging.log4j.util.Strings; import org.junit.After; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RolePermissionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RolePermissionTest.java index 645b02e232..436b1aabb3 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RolePermissionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/RolePermissionTest.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.unit.core; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.auth.HugePermission; import org.apache.hugegraph.auth.HugeProject; import org.apache.hugegraph.auth.HugeResource; @@ -27,8 +27,8 @@ import org.apache.hugegraph.auth.ResourceObject; import org.apache.hugegraph.auth.ResourceType; import org.apache.hugegraph.auth.RolePermission; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SchemaElementTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SchemaElementTest.java index 9853af107e..36f6f75f86 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SchemaElementTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SchemaElementTest.java @@ -17,23 +17,32 @@ package org.apache.hugegraph.unit.core; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.Userdata; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.EdgeLabelType; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.IdStrategy; import org.apache.hugegraph.unit.FakeObjects; import org.apache.hugegraph.util.DateUtil; +import org.apache.hugegraph.util.JsonUtil; import org.junit.Test; public class SchemaElementTest { @@ -270,4 +279,73 @@ public void testBulkSetterRejectsNullUserdata() { Assert.assertContains("userdata", e.getMessage()); }); } + + @Test + public void testEdgeLabelMetadataJsonRoundTrip() { + for (EdgeLabelType type : new EdgeLabelType[]{EdgeLabelType.NORMAL, + EdgeLabelType.PARENT, + EdgeLabelType.SUB}) { + for (boolean multipleLinks : new boolean[]{false, true}) { + EdgeLabel label = new EdgeLabel(null, IdGenerator.of(3), "knows"); + label.edgeLabelType(type); + label.frequency(Frequency.SINGLE); + label.links(Pair.of(IdGenerator.of(1), IdGenerator.of(2))); + if (multipleLinks) { + label.links(Pair.of(IdGenerator.of(2), IdGenerator.of(4))); + } + if (type.sub()) { + label.fatherId(IdGenerator.of(5)); + } + String json = JsonUtil.toJson(label.asMap()); + Map decoded = JsonUtil.fromJson(json, Map.class); + Assert.assertEquals(!multipleLinks, decoded.containsKey(EdgeLabel.P.SOURCE_LABEL)); + Assert.assertEquals(!multipleLinks, decoded.containsKey(EdgeLabel.P.TARGET_LABEL)); + Assert.assertTrue(decoded.containsKey(EdgeLabel.P.LINKS)); + + // Metadata JSON key order must not select setter execution order. + List keys = new ArrayList<>(decoded.keySet()); + Collections.reverse(keys); + Map reordered = new LinkedHashMap<>(); + reordered.put(EdgeLabel.P.LINKS, decoded.get(EdgeLabel.P.LINKS)); + for (String key : keys) { + reordered.put(key, decoded.get(key)); + } + for (Map input : Arrays.asList(decoded, reordered)) { + EdgeLabel restored = EdgeLabel.fromMap(input, null); + Assert.assertEquals(label.links(), restored.links()); + Assert.assertEquals(label.edgeLabelType(), restored.edgeLabelType()); + Assert.assertEquals(label.fatherId(), restored.fatherId()); + Assert.assertEquals(label.frequency(), restored.frequency()); + Assert.assertEquals(label.status(), restored.status()); + Assert.assertEquals(label.asMap(), restored.asMap()); + } + } + } + } + + + @Test + public void testOrderedSchemaFieldsSurviveMetadataJson() { + for (int[] values : new int[][]{{17, 2}, {2, 17}, {2, 17, 2}}) { + VertexLabel vertex = new VertexLabel(null, IdGenerator.of(1), "person"); + vertex.idStrategy(IdStrategy.PRIMARY_KEY); + EdgeLabel edge = new EdgeLabel(null, IdGenerator.of(3), "knows"); + edge.frequency(Frequency.SINGLE); + edge.links(Pair.of(IdGenerator.of(1), IdGenerator.of(2))); + for (int value : values) { + vertex.primaryKey(IdGenerator.of(value)); + edge.sortKey(IdGenerator.of(value)); + } + String vertexJson = JsonUtil.toJson(vertex.asMap()); + String edgeJson = JsonUtil.toJson(edge.asMap()); + VertexLabel restoredVertex = VertexLabel.fromMap( + JsonUtil.fromJson(vertexJson, Map.class), null); + EdgeLabel restoredEdge = EdgeLabel.fromMap(JsonUtil.fromJson(edgeJson, Map.class), null); + Assert.assertEquals(vertex.primaryKeys(), restoredVertex.primaryKeys()); + Assert.assertEquals(edge.sortKeys(), restoredEdge.sortKeys()); + Assert.assertEquals(vertex.asMap(), restoredVertex.asMap()); + Assert.assertEquals(edge.asMap(), restoredEdge.asMap()); + } + } + } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SecurityManagerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SecurityManagerTest.java index a30f35cb31..a39d1b138d 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SecurityManagerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SecurityManagerTest.java @@ -32,7 +32,7 @@ import java.util.Map; import java.util.concurrent.TimeoutException; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.auth.HugeFactoryAuthProxy; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ServerInfoManagerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ServerInfoManagerTest.java index 3784cef086..74cf096185 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ServerInfoManagerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/ServerInfoManagerTest.java @@ -18,7 +18,7 @@ package org.apache.hugegraph.unit.core; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.task.ServerInfoManager; import org.apache.hugegraph.testutil.Assert; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/StandardHugeGraphClearBackendTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/StandardHugeGraphClearBackendTest.java index f056c9291f..9aa9295f25 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/StandardHugeGraphClearBackendTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/StandardHugeGraphClearBackendTest.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.unit.core; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.StandardHugeGraph; import org.apache.hugegraph.backend.cache.CachedSchemaTransactionV2; import org.apache.hugegraph.backend.store.BackendStore; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SystemSchemaStoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SystemSchemaStoreTest.java index 96a0ce791c..e345ed3a21 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SystemSchemaStoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/SystemSchemaStoreTest.java @@ -18,11 +18,11 @@ package org.apache.hugegraph.unit.core; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.SystemSchemaStore; -import org.apache.hugegraph.schema.SchemaElement; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.junit.Test; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TaskSchedulerServerInfoTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TaskSchedulerServerInfoTest.java index f7dd3e370a..feef2f623c 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TaskSchedulerServerInfoTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TaskSchedulerServerInfoTest.java @@ -23,8 +23,8 @@ import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.HugeGraphParams; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.concurrent.PausableScheduledThreadPool; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.config.HugeConfig; @@ -32,7 +32,7 @@ import org.apache.hugegraph.core.GraphManager; import org.apache.hugegraph.event.EventHub; import org.apache.hugegraph.exception.NotFoundException; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.task.DistributedTaskScheduler; import org.apache.hugegraph.task.HugeTask; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TraversalUtilTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TraversalUtilTest.java index 08322112b7..fe664e1003 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TraversalUtilTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/core/TraversalUtilTest.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.unit.core; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.traversal.optimize.TraversalUtil; import org.apache.hugegraph.util.DateUtil; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/EdgeIdTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/EdgeIdTest.java index 0c917832f8..d36fe413a8 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/EdgeIdTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/EdgeIdTest.java @@ -19,9 +19,9 @@ import java.util.Set; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.unit.BaseUnitTest; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdTest.java index 8bd772a3db..c695e80f26 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdTest.java @@ -20,9 +20,9 @@ import java.nio.ByteBuffer; import java.util.UUID; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.Id.IdType; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.Id.IdType; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.unit.BaseUnitTest; import org.apache.hugegraph.util.NumericUtil; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdUtilTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdUtilTest.java index 473dc61891..38d1e4d876 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdUtilTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/IdUtilTest.java @@ -19,10 +19,10 @@ import java.nio.ByteBuffer; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.IdUtil; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdUtil; import org.junit.Assert; import org.junit.Test; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/SplicingIdGeneratorTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/SplicingIdGeneratorTest.java index bc7f97ccfb..50214b650b 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/SplicingIdGeneratorTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/id/SplicingIdGeneratorTest.java @@ -19,17 +19,14 @@ import java.util.List; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; -import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.BaseVertex; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.IdStrategy; -import org.apache.hugegraph.unit.FakeObjects; import org.junit.Test; -import org.mockito.Mockito; import com.google.common.collect.ImmutableList; @@ -37,15 +34,9 @@ public class SplicingIdGeneratorTest { @Test public void testGenerate() { - FakeObjects fakeObjects = new FakeObjects(); - PropertyKey name = fakeObjects.newPropertyKey(IdGenerator.of(1), - "name"); - VertexLabel vertexLabel = fakeObjects.newVertexLabel( - IdGenerator.of(1L), "fake", - IdStrategy.PRIMARY_KEY, name.id()); - HugeVertex vertex = Mockito.mock(HugeVertex.class); - Mockito.when(vertex.schemaLabel()).thenReturn(vertexLabel); - Mockito.when(vertex.name()).thenReturn("marko"); + VertexLabel vertexLabel = new VertexLabel(null, IdGenerator.of(1L), "fake"); + vertexLabel.idStrategy(IdStrategy.PRIMARY_KEY); + BaseVertex vertex = new BaseVertex(IdGenerator.of("1:marko"), vertexLabel); Id vid = SplicingIdGenerator.instance().generate(vertex); Assert.assertEquals(IdGenerator.of("1:marko"), vid); } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBCountersTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBCountersTest.java index cd42f2bccf..d7e5fc38a3 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBCountersTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBCountersTest.java @@ -21,8 +21,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions.Session; import org.apache.hugegraph.backend.store.rocksdb.RocksDBTables; import org.apache.hugegraph.testutil.Assert; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBPerfTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBPerfTest.java index 4256f290e3..dec44b917e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBPerfTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBPerfTest.java @@ -24,7 +24,7 @@ import java.util.Map; import java.util.Random; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions.Session; import org.junit.Test; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBSessionTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBSessionTest.java index 16b87d9a1c..700e466453 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBSessionTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBSessionTest.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.Random; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions.Session; import org.apache.hugegraph.testutil.Assert; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBTableQueryByIdsTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBTableQueryByIdsTest.java index 26598ba497..a50beb24b1 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBTableQueryByIdsTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/rocksdb/RocksDBTableQueryByIdsTest.java @@ -27,10 +27,10 @@ import java.util.Set; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.query.IdQuery; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.store.BackendEntry.BackendColumnIterator; import org.apache.hugegraph.backend.store.rocksdb.RocksDBSessions; import org.apache.hugegraph.backend.store.rocksdb.RocksDBTables; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryBackendEntryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryBackendEntryTest.java index 7c8a507021..bcaab2878f 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryBackendEntryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryBackendEntryTest.java @@ -18,7 +18,7 @@ package org.apache.hugegraph.unit.serializer; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.unit.BaseUnitTest; @@ -38,6 +38,7 @@ public void testColumns() { entry.columns(ImmutableList.of(col)); Assert.assertEquals(1, entry.columnsSize()); Assert.assertEquals(ImmutableList.of(col), entry.columns()); + Assert.assertSame(col, entry.columns().iterator().next()); entry.columns(ImmutableList.of(col, col)); Assert.assertEquals(3, entry.columnsSize()); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryScatterSerializerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryScatterSerializerTest.java index a0df546327..224867c71a 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryScatterSerializerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinaryScatterSerializerTest.java @@ -24,7 +24,6 @@ import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; -import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.unit.BaseUnitTest; import org.apache.hugegraph.unit.FakeObjects; import org.junit.Test; @@ -49,7 +48,7 @@ public void testVertex() { assertCollectionEquals(edge.targetVertex().getProperties(), vertex2.getProperties()); - Whitebox.setInternalState(vertex2, "removed", true); + vertex2.element().removed(true); Assert.assertTrue(vertex2.removed()); BackendEntry entry3 = ser.writeVertex(vertex2); Assert.assertEquals(0, entry3.columnsSize()); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinarySerializerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinarySerializerTest.java index 02d64bcc78..92fa5976bc 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinarySerializerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BinarySerializerTest.java @@ -19,27 +19,140 @@ import java.util.Arrays; import java.util.Date; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; import java.util.Set; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.Index.IdWithExpiredTime; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.IdStrategy; +import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.backend.serializer.BinarySerializer; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; -import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; import org.apache.hugegraph.unit.BaseUnitTest; import org.apache.hugegraph.unit.FakeObjects; import org.apache.hugegraph.util.DateUtil; import org.junit.Test; +import org.mockito.Mockito; public class BinarySerializerTest extends BaseUnitTest { + @Test + public void testLegacyStoredLabelExpiryReadEliminateAndAppendKeys() throws IOException { + Properties core = labelFixtures("core-rows.properties"); + Properties store = labelFixtures("store-index-rows.properties"); + long expiry = Long.parseLong(core.getProperty("expiry")); + FakeObjects objects = new FakeObjects("legacy-fixture"); + Mockito.when(objects.graph().now()).thenReturn(expiry + 1L); + BinarySerializer serializer = new BinarySerializer(); + for (String name : new String[]{"system", "system.edge"}) { + boolean edge = name.endsWith("edge"); + HugeType base = edge ? HugeType.EDGE : HugeType.VERTEX; + IndexLabel label = IndexLabel.label(base); + HugeType indexType = edge ? HugeType.EDGE_LABEL_INDEX : HugeType.VERTEX_LABEL_INDEX; + Id element = edge ? new EdgeId(IdGenerator.of(1L), Directions.OUT, + IdGenerator.of(5L), IdGenerator.of(5L), "2026!x", + IdGenerator.of(2L)) : IdGenerator.of(1L); + byte[] key = Bytes.fromHex(store.getProperty(name + ".name")); + byte[] value = Bytes.fromHex(store.getProperty(name + ".value")); + byte[] rowId = Bytes.fromHex(core.getProperty("index." + name + ".id")); + BinaryBackendEntry stored = new BinaryBackendEntry(indexType, rowId); + stored.column(key, value); + ConditionQuery query = new ConditionQuery(indexType); + query.eq(HugeKeys.FIELD_VALUES, edge ? 5L : 4L); + Index read = serializer.readIndex(objects.graph(), query, stored); + Assert.assertEquals(element, read.elementId()); + Assert.assertEquals(expiry, read.expiredTime()); + Assert.assertFalse(read.hasTtl()); + Set expired = read.expiredElementIds(); + Assert.assertEquals(1, expired.size()); + Assert.assertTrue(read.elementIds().isEmpty()); + Index removal = read.clone(); + removal.resetElementIds(); + for (IdWithExpiredTime record : expired) { + removal.elementIds(record.id(), record.expiredTime()); + } + BackendEntry removed = serializer.writeIndex(removal); + Assert.assertEquals(1, removed.columnsSize()); + BackendColumn removedColumn = removed.columns().iterator().next(); + Assert.assertArrayEquals(key, removedColumn.name); + Assert.assertNotNull(removedColumn.value); + Assert.assertArrayEquals(BytesBuffer.BYTES_EMPTY, removedColumn.value); + Assert.assertTrue(read.elementIds().isEmpty()); + + Index append = new Index(objects.graph(), label); + append.fieldValues(edge ? 5L : 4L); + append.elementIds(element, expiry); + BackendEntry appended = serializer.writeIndex(append); + BackendColumn appendedColumn = appended.columns().iterator().next(); + Assert.assertArrayEquals(key, appendedColumn.name); + Assert.assertArrayEquals(Bytes.fromHex(core.getProperty( + "index." + name + ".column.0.name")), appendedColumn.name); + Assert.assertNotNull(appendedColumn.value); + Assert.assertArrayEquals(Bytes.fromHex(core.getProperty( + "index." + name + ".column.0.value")), appendedColumn.value); + // Core append and TTL elimination address the original Store cell, + // so they cannot introduce a second key carrying an expiry suffix. + Assert.assertArrayEquals(removedColumn.name, appendedColumn.name); + Index appendedRead = serializer.readIndex(objects.graph(), query, appended); + Assert.assertEquals(1, appendedRead.elementIds().size()); + Assert.assertEquals(element, appendedRead.elementId()); + Assert.assertEquals(0L, appendedRead.expiredTime()); + } + } + + @Test + public void testOrdinaryIndexWriterProducesNonNullKvValue() { + FakeObjects objects = new FakeObjects(); + Id fieldId = IdGenerator.of(1L); + Id baseId = IdGenerator.of(2L); + objects.newPropertyKey(fieldId, "age", DataType.INT, Cardinality.SINGLE); + objects.newVertexLabel(baseId, "person", IdStrategy.CUSTOMIZE_NUMBER, fieldId); + IndexLabel label = objects.newIndexLabel(IdGenerator.of(3L), "by-age", HugeType.VERTEX_LABEL, + baseId, IndexType.SECONDARY, fieldId); + Index index = new Index(objects.graph(), label); + index.fieldValues("42"); + index.elementIds(IdGenerator.of(4L)); + + BackendEntry entry = new BinarySerializer().writeIndex(index); + Assert.assertEquals(1, entry.columnsSize()); + BackendColumn column = entry.columns().iterator().next(); + Assert.assertNotNull(column.name); + Assert.assertNotNull(column.value); + Assert.assertArrayEquals(BytesBuffer.BYTES_EMPTY, column.value); + } + + private static Properties labelFixtures(String name) throws IOException { + Properties fixtures = new Properties(); + try (InputStream input = BinarySerializerTest.class.getResourceAsStream( + "/compatibility/2f827d6e8/" + name)) { + Assert.assertNotNull(input); + fixtures.load(input); + } + return fixtures; + } + @Test public void testVertex() { HugeConfig config = FakeObjects.newConfig(); @@ -58,7 +171,7 @@ public void testVertex() { assertCollectionEquals(edge.targetVertex().getProperties(), vertex2.getProperties()); - Whitebox.setInternalState(vertex2, "removed", true); + vertex2.element().removed(true); Assert.assertTrue(vertex2.removed()); BackendEntry entry3 = ser.writeVertex(vertex2); Assert.assertEquals(0, entry3.columnsSize()); @@ -107,7 +220,7 @@ public void testVertexForPartition() { assertCollectionEquals(edge.targetVertex().getProperties(), vertex2.getProperties()); - Whitebox.setInternalState(vertex2, "removed", true); + vertex2.element().removed(true); Assert.assertTrue(vertex2.removed()); BackendEntry entry3 = ser.writeVertex(vertex2); Assert.assertEquals(0, entry3.columnsSize()); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BytesBufferTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BytesBufferTest.java index 8d82a7c6c8..af438b578f 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BytesBufferTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/BytesBufferTest.java @@ -30,13 +30,13 @@ import org.apache.hugegraph.HugeFactory; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.IdGenerator.UuidId; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator.UuidId; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; @@ -921,77 +921,77 @@ public void testProperty() { PropertyKey pkey = genPkey(DataType.BOOLEAN); Object value = true; byte[] bytes = genBytes("01"); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); value = false; bytes = genBytes("00"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.BYTE); value = (byte) 127; bytes = genBytes("7f"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.INT); value = 127; bytes = genBytes("7f"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.INT); value = 128; bytes = genBytes("8100"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.FLOAT); value = 1.0f; bytes = genBytes("3f800000"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.FLOAT); value = 3.14f; bytes = genBytes("4048f5c3"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.FLOAT); value = -1.0f; bytes = genBytes("bf800000"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.FLOAT); value = Float.MAX_VALUE; bytes = genBytes("7f7fffff"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.LONG); value = 127L; bytes = genBytes("7f"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.DOUBLE); value = 3.14d; bytes = genBytes("40091eb851eb851f"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.DATE); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Beijing")); @@ -999,53 +999,53 @@ public void testProperty() { value = c.getTime(); bytes = genBytes("adc9a098e22a"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.TEXT); value = "abc"; bytes = genBytes("03616263"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.BLOB); value = genBytes("001199aabbcc"); bytes = genBytes("06001199aabbcc"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); Assert.assertEquals(Blob.wrap((byte[]) value), - BytesBuffer.wrap(bytes).readProperty(pkey)); + BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.UUID); value = UUID.fromString("3cfcafc8-7906-4ab7-a207-4ded056f58de"); bytes = genBytes("3cfcafc879064ab7a2074ded056f58de"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.OBJECT); value = new Point(3, 8); bytes = genBytes("1301006a6176612e6177742e506f696ef4010610"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.OBJECT); value = UUID.fromString("3cfcafc8-7906-4ab7-a207-4ded056f58de"); bytes = genBytes("2101006a6176612e7574696c2e555549c401" + "3cfcafc879064ab7a2074ded056f58de"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genPkey(DataType.OBJECT); value = new int[]{1, 3, 8}; bytes = genBytes("0901005bc90104020610"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); Assert.assertArrayEquals((int[]) value, (int[]) - BytesBuffer.wrap(bytes).readProperty(pkey)); + BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); } @Test @@ -1054,50 +1054,50 @@ public void testPropertyWithList() { PropertyKey pkey = genListPkey(DataType.BOOLEAN); Object value = ImmutableList.of(true, false); byte[] bytes = genBytes("020100"); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.BYTE); value = ImmutableList.of(); bytes = genBytes("00"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.BYTE); value = ImmutableList.of((byte) 127, (byte) 128); bytes = genBytes("027f8fffffff00"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.INT); value = ImmutableList.of(127, 128); bytes = genBytes("027f8100"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.FLOAT); value = ImmutableList.of(1.0f, 3.14f); bytes = genBytes("023f8000004048f5c3"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.LONG); value = ImmutableList.of(127L, 128L); bytes = genBytes("027f8100"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.DOUBLE); value = ImmutableList.of(1.0d, 3.14d); bytes = genBytes("023ff000000000000040091eb851eb851f"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.DATE); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Beijing")); @@ -1105,22 +1105,22 @@ public void testPropertyWithList() { value = ImmutableList.of(c.getTime(), c.getTime()); bytes = genBytes("02adc9a098e22aadc9a098e22a"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.TEXT); value = ImmutableList.of("abc", "123"); bytes = genBytes("020361626303313233"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.BLOB); value = ImmutableList.of(genBytes("001199aabbcc"), genBytes("5566")); bytes = genBytes("0206001199aabbcc025566"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - List list = (List) BytesBuffer.wrap(bytes).readProperty(pkey); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + List list = (List) BytesBuffer.wrap(bytes).readSchemaProperty(pkey); Assert.assertEquals(Blob.wrap(genBytes("001199aabbcc")), list.get(0)); Assert.assertEquals(Blob.wrap(genBytes("5566")), list.get(1)); @@ -1130,23 +1130,23 @@ public void testPropertyWithList() { bytes = genBytes("023cfcafc879064ab7a2074ded056f58de" + "3cfcafc879064ab7a2074ded056f58de"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.OBJECT); value = ImmutableList.of(new Point(3, 8), new Point(3, 9)); bytes = genBytes("021301006a6176612e6177742e506f696ef4010610" + "1301006a6176612e6177742e506f696ef4010612"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genListPkey(DataType.OBJECT); value = ImmutableList.of(new int[]{1, 3}, new int[]{2, 5}); bytes = genBytes("020801005bc9010302060801005bc90103040a"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - list = (List) BytesBuffer.wrap(bytes).readProperty(pkey); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + list = (List) BytesBuffer.wrap(bytes).readSchemaProperty(pkey); Assert.assertArrayEquals(new int[]{1, 3}, (int[]) list.get(0)); Assert.assertArrayEquals(new int[]{2, 5}, (int[]) list.get(1)); } @@ -1157,50 +1157,50 @@ public void testPropertyWithSet() { PropertyKey pkey = genSetPkey(DataType.BOOLEAN); Object value = ImmutableSet.of(true, false); byte[] bytes = genBytes("020100"); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.BYTE); value = ImmutableSet.of(); bytes = genBytes("00"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.BYTE); value = ImmutableSet.of((byte) 127, (byte) 128); bytes = genBytes("027f8fffffff00"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.INT); value = ImmutableSet.of(127, 128); bytes = genBytes("027f8100"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.FLOAT); value = ImmutableSet.of(1.0f, 3.14f); bytes = genBytes("023f8000004048f5c3"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.LONG); value = ImmutableSet.of(127L, 128L); bytes = genBytes("027f8100"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.DOUBLE); value = ImmutableSet.of(1.0d, 3.14d); bytes = genBytes("023ff000000000000040091eb851eb851f"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.DATE); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Beijing")); @@ -1208,22 +1208,22 @@ public void testPropertyWithSet() { value = ImmutableSet.of(c.getTime(), c.getTime()); bytes = genBytes("01adc9a098e22a"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.TEXT); value = ImmutableSet.of("abc", "123"); bytes = genBytes("020361626303313233"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.BLOB); value = ImmutableSet.of(genBytes("001199aabbcc"), genBytes("5566")); bytes = genBytes("0206001199aabbcc025566"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Set set = (Set) BytesBuffer.wrap(bytes).readProperty(pkey); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Set set = (Set) BytesBuffer.wrap(bytes).readSchemaProperty(pkey); Iterator iterator = set.iterator(); Assert.assertEquals(Blob.wrap(genBytes("001199aabbcc")), iterator.next()); @@ -1234,23 +1234,23 @@ public void testPropertyWithSet() { value = ImmutableSet.of(uuid, uuid); bytes = genBytes("013cfcafc879064ab7a2074ded056f58de"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.OBJECT); value = ImmutableSet.of(new Point(3, 8), new Point(3, 9)); bytes = genBytes("021301006a6176612e6177742e506f696ef4010610" + "1301006a6176612e6177742e506f696ef4010612"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - Assert.assertEquals(value, BytesBuffer.wrap(bytes).readProperty(pkey)); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + Assert.assertEquals(value, BytesBuffer.wrap(bytes).readSchemaProperty(pkey)); pkey = genSetPkey(DataType.OBJECT); value = ImmutableSet.of(new int[]{1, 3}, new int[]{2, 5}); bytes = genBytes("020801005bc9010302060801005bc90103040a"); buf.forReadWritten(); - Assert.assertArrayEquals(bytes, buf.writeProperty(pkey, value).bytes()); - set = (Set) BytesBuffer.wrap(bytes).readProperty(pkey); + Assert.assertArrayEquals(bytes, buf.writeSchemaProperty(pkey, value).bytes()); + set = (Set) BytesBuffer.wrap(bytes).readSchemaProperty(pkey); iterator = set.iterator(); Assert.assertArrayEquals(new int[]{1, 3}, (int[]) iterator.next()); Assert.assertArrayEquals(new int[]{2, 5}, (int[]) iterator.next()); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/HugeGraphSONModuleTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/HugeGraphSONModuleTest.java index 5b7b5fa4ab..8f0af5417a 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/HugeGraphSONModuleTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/HugeGraphSONModuleTest.java @@ -25,13 +25,13 @@ import java.util.Map; import java.util.UUID; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.backend.id.IdGenerator.LongId; -import org.apache.hugegraph.backend.id.IdGenerator.StringId; -import org.apache.hugegraph.backend.id.IdGenerator.UuidId; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator.LongId; +import org.apache.hugegraph.id.IdGenerator.StringId; +import org.apache.hugegraph.id.IdGenerator.UuidId; import org.apache.hugegraph.io.HugeGraphIoRegistry; -import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.unit.BaseUnitTest; import org.apache.hugegraph.unit.FakeObjects; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/SerializerFactoryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/SerializerFactoryTest.java index 15294439db..2a241e30e2 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/SerializerFactoryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/SerializerFactoryTest.java @@ -25,7 +25,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.backend.serializer.AbstractSerializer; import org.apache.hugegraph.backend.serializer.BinaryScatterSerializer; import org.apache.hugegraph.backend.serializer.BinarySerializer; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/StoreSerializerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/StoreSerializerTest.java index 321f018de2..9d4497aa83 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/StoreSerializerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/StoreSerializerTest.java @@ -20,7 +20,7 @@ import java.util.Iterator; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; -import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.backend.store.BackendAction; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.backend.store.BackendMutation; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TableBackendEntryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TableBackendEntryTest.java index 2771764d48..2c27643d26 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TableBackendEntryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TableBackendEntryTest.java @@ -18,10 +18,10 @@ package org.apache.hugegraph.unit.serializer; import org.apache.commons.lang3.NotImplementedException; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.serializer.TableBackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextBackendEntryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextBackendEntryTest.java index 4700ca4afa..e016588bc5 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextBackendEntryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextBackendEntryTest.java @@ -17,9 +17,9 @@ package org.apache.hugegraph.unit.serializer; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.serializer.TextBackendEntry; -import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextSerializerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextSerializerTest.java index 4d55a9b046..8e5af99921 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextSerializerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/serializer/TextSerializerTest.java @@ -21,12 +21,12 @@ import java.util.Date; import java.util.Set; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.backend.serializer.TextSerializer; import org.apache.hugegraph.backend.store.BackendEntry; import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.Userdata; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/traversal/ShortestPathTraverserTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/traversal/ShortestPathTraverserTest.java index e3630a1109..c527212c53 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/traversal/ShortestPathTraverserTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/traversal/ShortestPathTraverserTest.java @@ -27,9 +27,9 @@ import java.util.Map; import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.config.CoreOptions; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.testutil.Assert; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/JsonUtilTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/JsonUtilTest.java index 722f747ed8..990841d928 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/JsonUtilTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/JsonUtilTest.java @@ -26,13 +26,13 @@ import java.util.UUID; import org.apache.commons.lang3.tuple.Pair; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.IndexLabel; -import org.apache.hugegraph.schema.PropertyKey; -import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeProperty; @@ -40,7 +40,6 @@ import org.apache.hugegraph.structure.HugeVertexProperty; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Utils; -import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.DataType; @@ -251,7 +250,7 @@ public void testSerializeVertexWithNumberId() { age.id(), new HugeVertexProperty<>(vertex, age, 29), city.id(), new HugeVertexProperty<>(vertex, city, "Beijing") ); - Whitebox.setInternalState(vertex, "properties", properties); + properties.values().forEach(vertex::setProperty); String json = JsonUtil.toJson(vertex); Assert.assertEquals("{\"id\":123456,\"label\":\"person\"," + @@ -291,8 +290,7 @@ public void testSerializeEdge() { Id id = EdgeId.parse("L123456>1>1>>L987654"); HugeEdge edge = new HugeEdge(fakeObject.graph(), id, el); - Whitebox.setInternalState(edge, "sourceVertex", source); - Whitebox.setInternalState(edge, "targetVertex", target); + edge.vertices(true, source, target); Date dateValue = Utils.date("2019-03-12"); MutableIntObjectMap> properties = @@ -300,7 +298,7 @@ public void testSerializeEdge() { date.id(), new HugeEdgeProperty<>(edge, date, dateValue), weight.id(), new HugeEdgeProperty<>(edge, weight, 0.8) ); - Whitebox.setInternalState(edge, "properties", properties); + properties.values().forEach(edge::setProperty); String json = JsonUtil.toJson(edge); Assert.assertEquals("{\"id\":\"L123456>1>1>>L987654\"," + diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/CollectionFactoryTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/CollectionFactoryTest.java index 9e4697d81a..917a3d6d44 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/CollectionFactoryTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/CollectionFactoryTest.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.Set; -import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.type.define.CollectionType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/IdSetTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/IdSetTest.java index 2a9082c831..02ceaaea66 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/IdSetTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/IdSetTest.java @@ -23,8 +23,8 @@ import java.util.UUID; import org.apache.commons.lang.RandomStringUtils; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.type.define.CollectionType; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/ObjectIntMappingTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/ObjectIntMappingTest.java index 4d74c5bd85..f712e9421b 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/ObjectIntMappingTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/util/collection/ObjectIntMappingTest.java @@ -23,8 +23,8 @@ import java.util.UUID; import org.apache.commons.lang.RandomStringUtils; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.util.collection.ObjectIntMapping; import org.apache.hugegraph.util.collection.ObjectIntMappingFactory; diff --git a/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/README.md b/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/README.md new file mode 100644 index 0000000000..3d491292eb --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/README.md @@ -0,0 +1,34 @@ + + +# Label index compatibility fixtures + +The licensed `core-rows.properties` and `store-index-rows.properties` are +byte-identical copies of the canonical fixtures under +`hugegraph-struct/src/test/resources/compatibility/2f827d6e8`, whose README +contains full provenance and whose producers preserve the original pinned +`2f827d6e8c9c62ae858f2fc122b3a192d015e2f4` writers and readers. + +Core fixture SHA-256: `d90cfe0b349edb832bf7425b6b8e2ddb06b3eff3f29e834cf8363b0d2fb84662`. +Store fixture SHA-256: `e9e9c967884d0d91b6cf6d5eabf2050a9bad0fe7898d1c47b58535ebdf1b9431`. + +Core system vertex/edge label writers receive a positive element expiry but +emit empty values and stable keys. Original Store writers use those same +keys and the exact 13-byte `0x00 + Base64(big-endian long)` value envelope. +`BinarySerializerTest.testLegacyStoredLabelExpiryReadEliminateAndAppendKeys` +verifies reading those old Store values, recovering expired candidates, +clone/reset isolation, and eliminating/appending the exact original key. diff --git a/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties b/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties new file mode 100644 index 0000000000..fd489e58c1 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties @@ -0,0 +1,108 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +now=1609459200000 +expiry=1609459260000 +vertex.type=VERTEX +vertex.id=0801 +vertex.ttl=60000 +vertex.columns=1 +vertex.column.0.name=0801 +vertex.column.0.value=08040301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +edge.out.type=EDGE_OUT +edge.out.id=08018208050805323032362178000802 +edge.out.ttl=60000 +edge.out.columns=1 +edge.out.column.0.name=08018208050805323032362178000802 +edge.out.column.0.value=0301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +edge.in.type=EDGE_IN +edge.in.id=08028c08050805323032362178000801 +edge.in.ttl=60000 +edge.in.columns=1 +edge.in.column.0.name=08028c08050805323032362178000801 +edge.in.column.0.value=0301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +olap.type=OLAP +olap.id=0801 +olap.ttl=0 +olap.columns=1 +olap.column.0.name=0801 +olap.column.0.value=092a +index.secondary.type=SECONDARY_INDEX +index.secondary.id=53493a363a616c69636500 +index.secondary.ttl=60000 +index.secondary.columns=1 +index.secondary.column.0.name=53493a363a616c696365000801aeebd9fdb460 +index.secondary.column.0.value= +index.int.type=RANGE_INT_INDEX +index.int.id=a00000000780000007 +index.int.ttl=60000 +index.int.columns=1 +index.int.column.0.name=a000000007800000070801aeebd9fdb460 +index.int.column.0.value= +index.long.type=RANGE_LONG_INDEX +index.long.id=a2000000088000000000000007 +index.long.ttl=60000 +index.long.columns=1 +index.long.column.0.name=a20000000880000000000000070801aeebd9fdb460 +index.long.column.0.value= +vertex.untimed.type=VERTEX +vertex.untimed.id=0803 +vertex.untimed.ttl=0 +vertex.untimed.columns=1 +vertex.untimed.column.0.name=0803 +vertex.untimed.column.0.value=080a0301070203078fffffff7f0703028fffffff7f07 +edge.untimed.type=EDGE_OUT +edge.untimed.id=080182080b080b000802 +edge.untimed.ttl=0 +edge.untimed.columns=1 +edge.untimed.column.0.name=080182080b080b000802 +edge.untimed.column.0.value=0301070203078fffffff7f0703028fffffff7f07 +index.secondary.untimed.type=SECONDARY_INDEX +index.secondary.untimed.id=53493a433a616c69636500 +index.secondary.untimed.ttl=0 +index.secondary.untimed.columns=1 +index.secondary.untimed.column.0.name=53493a433a616c696365000801 +index.secondary.untimed.column.0.value= +index.int.untimed.type=RANGE_INT_INDEX +index.int.untimed.id=a00000000d80000007 +index.int.untimed.ttl=0 +index.int.untimed.columns=1 +index.int.untimed.column.0.name=a00000000d800000070801 +index.int.untimed.column.0.value= +index.long.untimed.type=RANGE_LONG_INDEX +index.long.untimed.id=a20000000e8000000000000007 +index.long.untimed.ttl=0 +index.long.untimed.columns=1 +index.long.untimed.column.0.name=a20000000e80000000000000070801 +index.long.untimed.column.0.value= +index.hashed.type=SECONDARY_INDEX +index.hashed.id=53493a463a323234303534613200 +index.hashed.ttl=60000 +index.hashed.columns=1 +index.hashed.column.0.name=53493a463a3232343035346132000801aeebd9fdb460 +index.hashed.column.0.value=6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d +index.system.type=VERTEX_LABEL_INDEX +index.system.id=56493a2d313a3400 +index.system.ttl=0 +index.system.columns=1 +index.system.column.0.name=56493a2d313a34000801 +index.system.column.0.value= +index.system.edge.type=EDGE_LABEL_INDEX +index.system.edge.id=45493a2d323a3500 +index.system.edge.ttl=0 +index.system.edge.columns=1 +index.system.edge.column.0.name=45493a2d323a35007e08018208050805323032362178000802 +index.system.edge.column.0.value= diff --git a/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties b/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties new file mode 100644 index 0000000000..7f5a599ed4 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +secondary.name=53493a363a616c696365000801 +secondary.value=00414141426472732f576d413d +secondary.expiry=1609459260000 +int.name=a000000007800000070801 +int.value=00414141426472732f576d413d +int.expiry=1609459260000 +long.name=a20000000880000000000000070801 +long.value=00414141426472732f576d413d +long.expiry=1609459260000 +system.name=56493a2d313a34000801 +system.value=00414141426472732f576d413d +system.expiry=1609459260000 +system.edge.name=45493a2d323a35007e08018208050805323032362178000802 +system.edge.value=00414141426472732f576d413d +system.edge.expiry=1609459260000 diff --git a/hugegraph-store/docs/development-guide.md b/hugegraph-store/docs/development-guide.md index bdc36e07ef..c55b57b4a7 100644 --- a/hugegraph-store/docs/development-guide.md +++ b/hugegraph-store/docs/development-guide.md @@ -796,11 +796,23 @@ When adding third-party dependencies: 5. Update `install-dist/scripts/dependency/known-dependencies.txt` **Run Dependency Check**: + +Run from the repository root after building Server, PD and Store distributions +for the current revision: + ```bash -cd install-dist/scripts/dependency -./regenerate_known_dependencies.sh +mvn install -DskipTests -Dmaven.javadoc.skip=true +bash install-dist/scripts/dependency/regenerate_known_dependencies.sh current-dependencies.txt +bash install-dist/scripts/dependency/check_dependencies.sh ``` +This build prepares artifacts without running tests. The collector combines the +Maven runtime union with actual distribution libraries, including nested Spring +Boot jars; missing current-revision distribution libraries fail. Review both added +and removed names against `known-dependencies.txt`, including license/NOTICE +changes, before updating the approved list. Comparison is strict, and source-only +inspection is insufficient; verify the release platform/profile variants too. + ### Documentation **When to Update Docs**: diff --git a/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/query/QueryExecutor.java b/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/query/QueryExecutor.java index b4102bb373..9f6fd0dc8b 100644 --- a/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/query/QueryExecutor.java +++ b/hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/query/QueryExecutor.java @@ -45,6 +45,7 @@ import org.apache.hugegraph.store.grpc.query.Index; import org.apache.hugegraph.store.grpc.query.QueryRequest; import org.apache.hugegraph.store.grpc.query.QueryResponse; +import org.apache.hugegraph.store.grpc.query.QueryResultFormat; import org.apache.hugegraph.store.grpc.query.ScanType; import org.apache.hugegraph.store.grpc.query.ScanTypeParam; import org.apache.hugegraph.store.query.BaseElementComparator; @@ -191,7 +192,8 @@ private StreamKvIterator getIterator(String address, QueryRequest r public boolean hasNext() { if (element == null) { while (itr.hasNext()) { - element = fromKv(request.getTable(), itr.next(), hasAgg); + element = fromKv(request.getTable(), itr.next(), hasAgg, + !QueryResultFormat.returnsTaggedElements(request)); if (element != null) { break; } @@ -447,7 +449,7 @@ private static List getOrCreate(List list) { return new ArrayList<>(); } - private BaseElement fromKv(String table, Kv kv, boolean isAgg) { + private BaseElement fromKv(String table, Kv kv, boolean isAgg, boolean schemaRow) { if (isAgg) { return KvElement.of(KvSerializer.fromBytes(kv.getKey().toByteArray()), KvSerializer.fromObjectBytes(kv.getValue().toByteArray())); @@ -457,9 +459,11 @@ private BaseElement fromKv(String table, Kv kv, boolean isAgg) { BackendColumn.of(kv.getKey().toByteArray(), kv.getValue().toByteArray()); try { if (IN_EDGE_TABLE.equals(table) || OUT_EDGE_TABLE.equals(table)) { - return serializer.parseEdge(this.supplier, backendColumn, null, true); + return schemaRow ? serializer.parseSchemaEdge(this.supplier, backendColumn, null, true) : + serializer.parseEdge(this.supplier, backendColumn, null, true); } - return serializer.parseVertex(this.supplier, backendColumn, null); + return schemaRow ? serializer.parseSchemaVertex(this.supplier, backendColumn, null) : + serializer.parseVertex(this.supplier, backendColumn, null); } catch (Exception e) { log.error("parse element error,", e); return null; @@ -539,7 +543,7 @@ public boolean hasNext() { @Override public BaseElement next() { - return fromKv(query.getTable(), data.next(), false); + return fromKv(query.getTable(), data.next(), false, true); } }; }) @@ -574,7 +578,7 @@ public boolean hasNext() { @Override public BaseElement next() { - return fromKv(query.getTable(), data.next(), true); + return fromKv(query.getTable(), data.next(), true, false); } }; }) diff --git a/hugegraph-store/hg-store-core/pom.xml b/hugegraph-store/hg-store-core/pom.xml index cffafaf446..6d456af251 100644 --- a/hugegraph-store/hg-store-core/pom.xml +++ b/hugegraph-store/hg-store-core/pom.xml @@ -113,11 +113,6 @@ ${revision} compile - - org.apache.hugegraph - hugegraph-core - ${revision} - org.apache.hugegraph hg-store-common diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/HgStoreEngine.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/HgStoreEngine.java index 03eb5fe77b..948b1e8f43 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/HgStoreEngine.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/HgStoreEngine.java @@ -232,7 +232,11 @@ public void shutdown() { // exists even shut down. rpcServer = null; // close all db session - RocksDBFactory.getInstance().releaseAllGraphDB(); + try { + RocksDBFactory.getInstance().releaseAllGraphDB(); + } finally { + BusinessHandlerImpl.closeSchemaResources(); + } } public void snapshotForTest() { diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/AbstractSelectIterator.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/AbstractSelectIterator.java index 40f909b0d2..47ea660ca7 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/AbstractSelectIterator.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/AbstractSelectIterator.java @@ -17,6 +17,9 @@ package org.apache.hugegraph.store.business; +import java.util.Objects; + +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.rocksdb.access.ScanIterator; import org.apache.hugegraph.serializer.BinaryElementSerializer; @@ -29,8 +32,10 @@ public abstract class AbstractSelectIterator implements ScanIterator { protected ScanIterator iterator; protected BinaryElementSerializer serializer; + protected final HugeGraphSupplier graph; - public AbstractSelectIterator() { + public AbstractSelectIterator(HugeGraphSupplier graph) { + this.graph = Objects.requireNonNull(graph, "graph"); this.serializer = new BinaryElementSerializer(); } @@ -39,9 +44,9 @@ public BaseElement parseEntry(BackendColumn column, boolean isVertex) { throw new IllegalArgumentException("BackendColumn cannot be null"); } if (isVertex) { - return serializer.parseVertex(null, column, null); + return serializer.parseSchemaVertex(this.graph, column, null); } else { - return serializer.parseEdge(null, column, null, true); + return serializer.parseSchemaEdge(this.graph, column, null, true); } } } diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/BusinessHandlerImpl.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/BusinessHandlerImpl.java index 38bad3b9e8..bc446afb31 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/BusinessHandlerImpl.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/BusinessHandlerImpl.java @@ -61,7 +61,6 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.hugegraph.HugeGraphSupplier; -import org.apache.hugegraph.SchemaGraph; import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.OptionSpace; @@ -112,6 +111,8 @@ import org.apache.hugegraph.store.query.QueryTypeParam; import org.apache.hugegraph.store.raft.RaftClosure; import org.apache.hugegraph.store.raft.RaftOperation; +import org.apache.hugegraph.store.schema.SchemaDriver; +import org.apache.hugegraph.store.schema.SchemaGraph; import org.apache.hugegraph.store.term.Bits; import org.apache.hugegraph.store.term.HgPair; import org.apache.hugegraph.store.util.DefaultThreadFactory; @@ -294,20 +295,32 @@ public static HugeGraphSupplier getGraphSupplier(String graph) { return mockGraphSupplier; } - if (GRAPH_SUPPLIER_CACHE.get(graph) == null) { + if (graph == null) { + throw new HgStoreException("Graph must include graph space and graph name"); + } + HugeGraphSupplier supplier = GRAPH_SUPPLIER_CACHE.get(graph); + if (supplier == null) { synchronized (BusinessHandlerImpl.class) { - if (GRAPH_SUPPLIER_CACHE.get(graph) == null) { + supplier = GRAPH_SUPPLIER_CACHE.get(graph); + if (supplier == null) { + if (HgStoreEngine.getInstance().isClosing().get()) { + throw new HgStoreException("Store is closing"); + } + String[] parts = graph.split("/", -1); + if (parts.length < 2 || parts[0].isEmpty() || parts[1].isEmpty()) { + throw new HgStoreException("Graph must include graph space and graph name: " + graph); + } var config = PDConfig.of(HgStoreEngine.getInstance().getOption().getPdAddress()); config.setAuthority(DefaultPdProvider.name, DefaultPdProvider.authority); - String[] parts = graph.split("/"); - assert (parts.length > 1); - GRAPH_SUPPLIER_CACHE.put(graph, new SchemaGraph(parts[0], parts[1], config)); + supplier = new SchemaGraph(parts[0], parts[1], config, + HgStoreEngine.getInstance().getOption().getPdCluster()); + GRAPH_SUPPLIER_CACHE.put(graph, supplier); } } } - return GRAPH_SUPPLIER_CACHE.get(graph); + return supplier; } @Override @@ -546,7 +559,17 @@ public ScanIterator scan(String graph, int code, String table, byte[] start, byt @Override public GraphStoreIterator scan(ScanPartitionRequest spr) throws HgStoreException { - return new GraphStoreIterator(scanOriginal(spr), spr); + ScanIterator original = scanOriginal(spr); + try { + return new GraphStoreIterator(original, spr); + } catch (RuntimeException failure) { + try { + original.close(); + } catch (RuntimeException closeFailure) { + failure.addSuppressed(closeFailure); + } + throw failure; + } } private ToLongFunction getBaseElementHashFunction() { @@ -739,7 +762,7 @@ public ScanIterator indexIntersection(String graph, String table, List { - if (filterTTL && isIndexExpire(column, now)) { + if (filterTTL && isIndexExpire(graph, column, now)) { return null; } - // todo: Use parseIndex(BackendColumn indexCol) later - var index = serializer.parseIndex(getGraphSupplier(graph), - BackendColumn.of(column.name, column.value), null); + var index = serializer.parseSchemaIndex(getGraphSupplier(graph), + BackendColumn.of(column.name, column.value)); if (param.getIdPrefix() != null && !Bytes.prefixWith(index.elementId().asBytes(), param.getIdPrefix())) { @@ -916,7 +938,7 @@ private ScanIterator scanIndexToBaseElement(String graph, QueryTypeParam param, param.getBoundary()) : scanPrefix(graph, param.getCode(), INDEX_TABLE, param.getStart(), param.getBoundary()), column -> { - if (filterTTL && isIndexExpire(column, now)) { + if (filterTTL && isIndexExpire(graph, column, now)) { return null; } @@ -934,8 +956,8 @@ private ScanIterator scanIndexToBaseElement(String graph, QueryTypeParam param, }, "trans-index-to-base-element"); } - private boolean isIndexExpire(RocksDBSession.BackendColumn column, long now) { - var e = directBinarySerializer.parseIndex(column.name, column.value); + private boolean isIndexExpire(String graph, RocksDBSession.BackendColumn column, long now) { + var e = directBinarySerializer.parseSchemaIndex(getGraphSupplier(graph), column.name, column.value); return e.expiredTime() > 0 && e.expiredTime() < now; } @@ -1131,9 +1153,13 @@ public void closeDB(int partId) { @Override public void closeAll() { log.warn("close all db!!! "); - factory.getGraphNames().forEach(dbName -> { - factory.releaseGraphDB(dbName); - }); + try { + factory.getGraphNames().forEach(dbName -> { + factory.releaseGraphDB(dbName); + }); + } finally { + closeSchemaResources(); + } } @Override @@ -1983,7 +2009,15 @@ private void release() { } } - public static void clearCache() { + public static synchronized void clearCache() { GRAPH_SUPPLIER_CACHE.clear(); } + + public static synchronized void closeSchemaResources() { + try { + SchemaDriver.destroy(); + } finally { + GRAPH_SUPPLIER_CACHE.clear(); + } + } } diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/DataManagerImpl.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/DataManagerImpl.java index 3a4b5ac26c..a27e6892ff 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/DataManagerImpl.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/DataManagerImpl.java @@ -51,6 +51,7 @@ import org.apache.hugegraph.store.raft.RaftOperation; import org.apache.hugegraph.store.term.Bits; import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.structure.BaseEdge; import org.apache.hugegraph.structure.BaseElement; import org.apache.hugegraph.structure.BaseVertex; @@ -292,17 +293,21 @@ public Status doBuildIndex(Metapb.BuildIndexParam param, Metapb.Partition source try { if (param.getIsVertexLabel()) { - element = serializer.parseVertex(graphSupplier, column, null); + element = serializer.parseSchemaVertex(graphSupplier, column, null); } else { - element = serializer.parseEdge(graphSupplier, column, null, true); + element = serializer.parseSchemaEdge(graphSupplier, column, null, true); } } catch (Exception e) { log.error("parse element failed, graph:{}, key:{}", graphName, e); continue; } - // filter by label id - if (!element.schemaLabel().id().equals(labelId)) { + boolean matchesLabel = element.schemaLabel().id().equals(labelId); + if (!matchesLabel && element instanceof BaseEdge) { + EdgeLabel edgeLabel = (EdgeLabel) element.schemaLabel(); + matchesLabel = edgeLabel.hasFather() && labelId.equals(edgeLabel.fatherId()); + } + if (!matchesLabel) { continue; } @@ -327,7 +332,7 @@ public Status doBuildIndex(Metapb.BuildIndexParam param, Metapb.Partition source } for (var index : array) { - var col = serializer.writeIndex(index); + var col = serializer.writeSchemaIndex(index); int code = PartitionUtils.calcHashcode(KeyUtil.getOwnerId(index.elementId())); // same partition id with element batch.add(partitionId, BatchPutRequest.KV.of(INDEX_TABLE, code, col.name, diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/FilterIterator.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/FilterIterator.java index eb53a2d254..531df3e953 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/FilterIterator.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/FilterIterator.java @@ -18,6 +18,7 @@ package org.apache.hugegraph.store.business; import org.apache.commons.lang3.ArrayUtils; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.rocksdb.access.RocksDBSession; @@ -34,20 +35,32 @@ public class FilterIterator extends private final ConditionQuery query; T current = null; - public FilterIterator(ScanIterator iterator, ConditionQuery query) { - super(); + public FilterIterator(ScanIterator iterator, ConditionQuery query, HugeGraphSupplier graph) { + super(graph); this.iterator = iterator; this.query = query; // log.info("operator sinking is used to filter data:{}", // query.toString()); } - public static ScanIterator of(ScanIterator it, byte[] conditionQuery) { + public static ScanIterator of(ScanIterator it, byte[] conditionQuery, String graph) { if (ArrayUtils.isEmpty(conditionQuery)) { return it; } - ConditionQuery query = ConditionQuery.fromBytes(conditionQuery); - return new FilterIterator(it, query); + try { + ConditionQuery query = ConditionQuery.fromBytes(conditionQuery); + if (!query.resultType().isVertex() && !query.resultType().isEdge()) { + return it; + } + return new FilterIterator(it, query, BusinessHandlerImpl.getGraphSupplier(graph)); + } catch (RuntimeException failure) { + try { + it.close(); + } catch (RuntimeException closeFailure) { + failure.addSuppressed(closeFailure); + } + throw failure; + } } @Override @@ -60,11 +73,11 @@ public boolean hasNext() { current = iterator.next(); BaseElement element; if (this.query.resultType().isVertex()) { - element = serializer.parseVertex(null, + element = serializer.parseSchemaVertex(this.graph, BackendColumn.of(current.name, current.value), null); } else { - element = serializer.parseEdge(null, + element = serializer.parseSchemaEdge(this.graph, BackendColumn.of(current.name, current.value), null, true); } diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/GraphStoreIterator.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/GraphStoreIterator.java index 51b9c8d15c..254915032e 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/GraphStoreIterator.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/GraphStoreIterator.java @@ -83,7 +83,7 @@ public class GraphStoreIterator extends AbstractSelectIterator public GraphStoreIterator(ScanIterator iterator, ScanPartitionRequest scanRequest) { - super(); + super(BusinessHandlerImpl.getGraphSupplier(scanRequest.getScanRequest().getGraphName())); this.iter = iterator; this.scanRequest = scanRequest; this.request = this.scanRequest.getScanRequest(); diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/SelectIterator.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/SelectIterator.java index 2b51e98778..542b91b5e2 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/SelectIterator.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/business/SelectIterator.java @@ -17,56 +17,64 @@ package org.apache.hugegraph.store.business; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; +import java.util.Objects; import java.util.List; import java.util.Set; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.rocksdb.access.RocksDBSession.BackendColumn; import org.apache.hugegraph.rocksdb.access.ScanIterator; import org.apache.hugegraph.serializer.BytesBuffer; -import org.apache.hugegraph.type.define.DataType; -import org.apache.hugegraph.type.define.SerialEnum; public class SelectIterator implements ScanIterator { - ScanIterator iter; - Set properties; + private final ScanIterator iter; + private final Set properties; + private final HugeGraphSupplier graph; + private final boolean isVertex; - public SelectIterator(ScanIterator iterator, List properties) { + public SelectIterator(ScanIterator iterator, List properties, + HugeGraphSupplier graph, boolean isVertex) { this.iter = iterator; - this.properties = new HashSet<>(properties); + this.properties = properties == null ? Collections.emptySet() : new HashSet<>(properties); + this.graph = this.properties.isEmpty() ? graph : Objects.requireNonNull(graph, "graph"); + this.isVertex = isVertex; } public BackendColumn select(BackendColumn column) { - int size; - if (properties == null || (size = properties.size()) == 0) { + if (this.properties.isEmpty() || column.value == null || column.value.length == 0) { return column; } - byte[] name = column.name; - byte[] value = column.value; - BytesBuffer buffer = BytesBuffer.wrap(value); - Id labelId = buffer.readId(); // label - int bpSize = buffer.readVInt(); // property - if (size == bpSize) { - return column; - } - BytesBuffer allocate = BytesBuffer.allocate(8 + 16 * size); - allocate.writeId(labelId); - allocate.writeVInt(size); - for (int i = 0; i < bpSize; i++) { + BytesBuffer buffer = BytesBuffer.wrap(column.value); + Id labelId = this.isVertex ? buffer.readId() : null; + int count = buffer.readVInt(); + List selected = new ArrayList<>(Math.min(count, this.properties.size())); + for (int i = 0; i < count; i++) { + int start = buffer.position(); int propertyId = buffer.readVInt(); - byte cat = buffer.read(); // cardinality and type - byte code = BytesBuffer.getType(cat); - DataType dataType = SerialEnum.fromCode(DataType.class, code); - Object bpValue = buffer.readProperty(dataType); - if (properties.contains(propertyId)) { - allocate.writeVInt(propertyId); - allocate.write(cat); - allocate.writeProperty(dataType, bpValue); + buffer.skipSchemaProperty(this.graph.propertyKey(IdGenerator.of(propertyId))); + if (this.properties.contains(propertyId)) { + // Preserve the stored bytes, including collection ordering and scalar representation. + selected.add(Arrays.copyOfRange(column.value, start, buffer.position())); } } - return BackendColumn.of(name, allocate.bytes()); + BytesBuffer output = BytesBuffer.allocate(column.value.length); + if (this.isVertex) { + output.writeId(labelId); + } + output.writeVInt(selected.size()); + for (byte[] property : selected) { + output.write(property); + } + // TTL belongs to the row, independently of which properties were selected. + output.write(buffer.remainingBytes()); + return BackendColumn.of(column.name, output.bytes()); } @Override diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java index aa5a1af109..e15070bc1b 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java @@ -53,6 +53,8 @@ public class HgStoreEngineOptions { private QueryPushDownOption queryPushDownOption = new QueryPushDownOption(); // pd server address private String pdAddress; + // PD metadata namespace; must match Server cluster/pd.cluster. + private String pdCluster = "hg"; // External service address private String grpcAddress; // Raft external service address diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/SchemaDriver.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema/SchemaDriver.java similarity index 91% rename from hugegraph-struct/src/main/java/org/apache/hugegraph/SchemaDriver.java rename to hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema/SchemaDriver.java index 11849b80ae..c81b6e8868 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/SchemaDriver.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema/SchemaDriver.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.hugegraph; +package org.apache.hugegraph.store.schema; import java.io.IOException; import java.util.ArrayList; @@ -32,6 +32,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.id.Id; @@ -64,7 +65,7 @@ public class SchemaDriver { public static final String META_PATH_HUGEGRAPH = "HUGEGRAPH"; public static final String META_PATH_GRAPHSPACE = "GRAPHSPACE"; public static final String META_PATH_GRAPH = "GRAPH"; - public static final String META_PATH_CLUSTER = "hg"; + public static final String DEFAULT_CLUSTER = "hg"; public static final String META_PATH_SCHEMA = "SCHEMA"; public static final String META_PATH_GRAPH_CONF = "GRAPH_CONF"; public static final String META_PATH_PROPERTY_KEY = "PROPERTY_KEY"; @@ -84,16 +85,23 @@ public class SchemaDriver { private static CountDownLatch destroyCompletion = new CountDownLatch(0); // Client for accessing PD private final KvClient client; + private final String cluster; private final SchemaCaches caches; - private SchemaDriver(PDConfig pdConfig, int cacheSize, + private SchemaDriver(PDConfig pdConfig, String cluster, int cacheSize, long expiration) { - this(new KvClient<>(pdConfig), cacheSize, expiration); + this(new KvClient<>(pdConfig), cluster, cacheSize, expiration); } - SchemaDriver(KvClient client, int cacheSize, + SchemaDriver(KvClient client, int cacheSize, long expiration) { + this(client, DEFAULT_CLUSTER, cacheSize, expiration); + } + + SchemaDriver(KvClient client, String cluster, int cacheSize, long expiration) { + E.checkArgument(cluster != null && !cluster.isEmpty(), "PD cluster cannot be empty"); + this.cluster = cluster; this.client = Objects.requireNonNull(client, "client"); this.caches = new SchemaCaches(cacheSize, expiration); try { @@ -117,6 +125,11 @@ public static void init(PDConfig pdConfig) { } public static void init(PDConfig pdConfig, int cacheSize, long expiration) { + init(pdConfig, DEFAULT_CLUSTER, cacheSize, expiration); + } + + public static void init(PDConfig pdConfig, String cluster, int cacheSize, long expiration) { + E.checkArgument(cluster != null && !cluster.isEmpty(), "PD cluster cannot be empty"); synchronized (LIFECYCLE_LOCK) { if (destroying) { throw new NotAllowException("The SchemaDriver is being destroyed"); @@ -129,7 +142,25 @@ public static void init(PDConfig pdConfig, int cacheSize, long expiration) { "allowed to be initialized again", instance.caches.limit(), instance.caches.expiration(), instance.client); } - INSTANCE.set(new SchemaDriver(pdConfig, cacheSize, expiration)); + INSTANCE.set(new SchemaDriver(pdConfig, cluster, cacheSize, expiration)); + } + } + + public static SchemaDriver getOrInit(PDConfig pdConfig, String cluster) { + E.checkArgument(cluster != null && !cluster.isEmpty(), "PD cluster cannot be empty"); + synchronized (LIFECYCLE_LOCK) { + if (destroying) { + throw new NotAllowException("The SchemaDriver is being destroyed"); + } + SchemaDriver instance = INSTANCE.get(); + if (instance == null) { + instance = new SchemaDriver(pdConfig, cluster, 300, 300 * 1000); + INSTANCE.set(instance); + } else if (!instance.cluster.equals(cluster)) { + throw new NotAllowException("SchemaDriver already uses PD cluster '%s', requested '%s'", + instance.cluster, cluster); + } + return instance; } } @@ -206,13 +237,32 @@ private void listenMetaChanges() { private void schemaCacheClearHandler(T response) { List names = this.extractValuesFromResponse(response); - for (String gs : names) { - String[] arr = gs.split(DELIMITER); - assert arr.length == 2; - this.caches.clear(arr[0], arr[1]); + for (String value : names) { + String graph = schemaCacheClearGraph(value); + if (graph == null) { + continue; + } + this.caches.clearByGraphName(graph); log.info(String.format( "Graph '%s' schema clear event is received, deleting all " + - "schema caches under '%s'", gs, gs)); + "schema caches under '%s'", graph, graph)); + } + } + + private String schemaCacheClearGraph(String value) { + if (value == null || value.isEmpty()) { + return null; + } + String payload = value.trim(); + if (!payload.startsWith("{")) { + return value; + } + try { + Object graph = fromJson(payload, Map.class).get("graph"); + return graph instanceof String && !((String) graph).isEmpty() ? (String) graph : null; + } catch (HugeException e) { + log.warn("Ignoring malformed schema cache clear event", e); + return null; } } @@ -380,7 +430,7 @@ private String propertyKeyPrefix(String graphSpace, String graph) { // }/SCHEMA/PROPERTY_KEY/NAME return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, graph, @@ -394,7 +444,7 @@ private String vertexLabelPrefix(String graphSpace, String graph) { // }/SCHEMA/VERTEX_LABEL/NAME return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, graph, @@ -408,7 +458,7 @@ private String edgeLabelPrefix(String graphSpace, String graph) { // }/SCHEMA/EDGELABEL/NAME return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, graph, @@ -422,7 +472,7 @@ private String indexLabelPrefix(String graphSpace, String graph) { // }/SCHEMA/INDEX_LABEL/NAME return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, graph, @@ -681,7 +731,7 @@ private String graphSpaceRemoveKey() { // HUGEGRAPH/{cluster}/EVENT/GRAPHSPACE/REMOVE return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_EVENT, META_PATH_GRAPHSPACE, META_PATH_REMOVE); @@ -691,7 +741,7 @@ private String graphConfKey(String graphSpace, String graph) { // HUGEGRAPH/{cluster}/GRAPHSPACE/{graphspace}/GRAPH_CONF/{graph} return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, META_PATH_GRAPH_CONF, @@ -704,7 +754,7 @@ private String nameKey(String graphSpace, String graph, // /{META_PATH_TYPE}/NAME/{name} return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, graph, @@ -720,7 +770,7 @@ private String idKey(String graphSpace, String graph, // /{META_PATH_TYPE}/ID/{id} return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_GRAPHSPACE, graphSpace, graph, @@ -734,7 +784,7 @@ private String schemaCacheClearKey() { // HUGEGRAPH/{cluster}/EVENT/GRAPH/SCHEMA/CLEAR return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_EVENT, META_PATH_GRAPH, META_PATH_SCHEMA, @@ -745,7 +795,7 @@ private String graphClearKey() { // HUGEGRAPH/{cluster}/EVENT/GRAPH/CLEAR return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_EVENT, META_PATH_GRAPH, META_PATH_CLEAR); @@ -755,7 +805,7 @@ private String graphRemoveKey() { // HUGEGRAPH/{cluster}/EVENT/GRAPH/REMOVE return stringJoin(META_PATH_DELIMITER, META_PATH_HUGEGRAPH, - META_PATH_CLUSTER, + this.cluster, META_PATH_EVENT, META_PATH_GRAPH, META_PATH_REMOVE); @@ -899,9 +949,11 @@ public void clearAll() { } public void clear(String graphSpace, String graph) { - ConcurrentHashMap - schemaCaches = - this.caches.get(stringJoin(DELIMITER, graphSpace, graph)); + this.clearByGraphName(stringJoin(DELIMITER, graphSpace, graph)); + } + + public void clearByGraphName(String graphName) { + ConcurrentHashMap schemaCaches = this.caches.get(graphName); if (schemaCaches != null) { schemaCaches.clear(); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/SchemaGraph.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema/SchemaGraph.java similarity index 91% rename from hugegraph-struct/src/main/java/org/apache/hugegraph/SchemaGraph.java rename to hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema/SchemaGraph.java index ed7241f7ad..ba9270e280 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/SchemaGraph.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/schema/SchemaGraph.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.hugegraph; +package org.apache.hugegraph.store.schema; import java.util.ArrayList; import java.util.Collection; @@ -26,6 +26,7 @@ import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.MapConfiguration; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.pd.client.PDConfig; @@ -40,30 +41,21 @@ public class SchemaGraph implements HugeGraphSupplier { private final String graphSpace; private final String graph; - private final PDConfig pdConfig; private final HugeConfig config; private final SchemaDriver schemaDriver; public SchemaGraph(String graphSpace, String graph, PDConfig pdConfig) { + this(graphSpace, graph, pdConfig, SchemaDriver.DEFAULT_CLUSTER); + } + + public SchemaGraph(String graphSpace, String graph, PDConfig pdConfig, String cluster) { this.graphSpace = graphSpace; this.graph = graph; - this.pdConfig = pdConfig; - this.schemaDriver = schemaDriverInit(); + this.schemaDriver = SchemaDriver.getOrInit(pdConfig, cluster); this.config = this.loadConfig(); } - private SchemaDriver schemaDriverInit() { - if (SchemaDriver.getInstance() == null) { - synchronized (SchemaDriver.class) { - if (SchemaDriver.getInstance() == null) { - SchemaDriver.init(this.pdConfig); - } - } - } - return SchemaDriver.getInstance(); - } - private HugeConfig loadConfig() { // Load configuration from PD Map configs = diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/util/UnsafeUtil.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/util/UnsafeUtil.java index bff726d4fd..e36565c858 100644 --- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/util/UnsafeUtil.java +++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/util/UnsafeUtil.java @@ -52,11 +52,7 @@ public static boolean hasUnsafe() { public static Object getUnsafe0() { Object unsafe; try { - // Accessing the Unsafe class and its singleton instance - final Class unsafeClass = Class.forName("sun.misc.Unsafe"); - final Field unsafeField = unsafeClass.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); // Bypass access checks - unsafe = unsafeField.get(null); // Get the Unsafe instance + unsafe = org.apache.hugegraph.util.UnsafeUtil.getUnsafe(); } catch (final Throwable t) { // Log a warning if Unsafe is not available if (log.isWarnEnabled()) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotFoundException.java b/hugegraph-store/hg-store-grpc/src/main/dev/org/apache/hugegraph/store/grpc/query/QueryResultFormat.java similarity index 50% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotFoundException.java rename to hugegraph-store/hg-store-grpc/src/main/dev/org/apache/hugegraph/store/grpc/query/QueryResultFormat.java index 7fb8c2317a..132833cf9e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/NotFoundException.java +++ b/hugegraph-store/hg-store-grpc/src/main/dev/org/apache/hugegraph/store/grpc/query/QueryResultFormat.java @@ -15,23 +15,25 @@ * limitations under the License. */ -package org.apache.hugegraph.exception; +package org.apache.hugegraph.store.grpc.query; -import org.apache.hugegraph.HugeException; - -public class NotFoundException extends HugeException { - - private static final long serialVersionUID = -5912665926327173032L; +/** + * Existing query responses carry either persistent rows or tagged graph elements. + * Keep their selection aligned with the node's deserialization stage. + */ +public final class QueryResultFormat { - public NotFoundException(String message) { - super(message); + private QueryResultFormat() { } - public NotFoundException(String message, Object... args) { - super(message, args); + public static boolean returnsTaggedElements(QueryRequest request) { + return request.getScanType() == ScanType.NO_SCAN && request.getLoadPropertyFromIndex() || + requiresElementDeserialization(request); } - public NotFoundException(String message, Throwable cause, Object... args) { - super(message, cause, args); + public static boolean requiresElementDeserialization(QueryRequest request) { + return request.getOrderByCount() > 0 || request.getPropertyCount() > 0 || + !request.getCondition().isEmpty() || + request.getFunctionsCount() > 0 && !request.getGroupBySchemaLabel(); } } diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java index 3f1624c087..c69f5fe89d 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java @@ -40,6 +40,9 @@ public class AppConfig { @Value("${pdserver.address}") private String pdServerAddress; + @Value("${pd.cluster:hg}") + private String pdCluster = "hg"; + @Value("${grpc.host}") private String host; diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java index 16592882b2..17cec42e71 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java @@ -84,6 +84,7 @@ public void init() { setDataPath(appConfig.getDataPath()); setRaftPath(appConfig.getRaftPath()); setPdAddress(appConfig.getPdServerAddress()); + setPdCluster(appConfig.getPdCluster()); setFakePD(appConfig.isFakePd()); setRocksdbConfig(appConfig.getRocksdbConfig()); setGrpcAddress(appConfig.getStoreServerAddress()); diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java index eae9534e89..54afcfda07 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java @@ -52,7 +52,7 @@ public boolean doClean(String graph, int partId) { public ScanIterator scanAll(String graph, String table, byte[] query) { ScanIterator scanIterator = this.handler.scanAll(graph, table, query); - return FilterIterator.of(scanIterator, query); + return FilterIterator.of(scanIterator, query, graph); } public ScanIterator scan(String graph, int partId, String table, byte[] start, byte[] end, @@ -60,14 +60,14 @@ public ScanIterator scan(String graph, int partId, String table, byte[] start, b byte[] query) { ScanIterator scanIterator = this.handler.scan(graph, partId, table, start, end, scanType, query); - return FilterIterator.of(scanIterator, query); + return FilterIterator.of(scanIterator, query, graph); } public ScanIterator scanOrdered(String graph, String table, byte[] start, byte[] end, int scanType, byte[] query) { ScanIterator scanIterator = this.handler.scanOrdered(graph, table, start, end, scanType); - return FilterIterator.of(scanIterator, query); + return FilterIterator.of(scanIterator, query, graph); } public void batchGet(String graph, String table, Supplier> s, @@ -82,7 +82,7 @@ public ScanIterator scanPrefix(String graph, int partition, String table, byte[] byte[] query) { ScanIterator scanIterator = this.handler.scanPrefix(graph, partition, table, prefix, scanType); - return FilterIterator.of(scanIterator, query); + return FilterIterator.of(scanIterator, query, graph); } public void doBatch(String graph, int partId, List entryList) { diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java index a1a706edcc..b7678f91d9 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java @@ -35,7 +35,9 @@ import org.apache.hugegraph.pd.common.KVPair; import org.apache.hugegraph.rocksdb.access.ScanIterator; +import org.apache.hugegraph.store.business.BusinessHandlerImpl; import org.apache.hugegraph.store.business.SelectIterator; +import org.apache.hugegraph.store.constant.HugeServerTables; import org.apache.hugegraph.store.grpc.common.ScanMethod; import org.apache.hugegraph.store.grpc.common.ScanOrderType; import org.apache.hugegraph.store.grpc.stream.ScanQueryRequest; @@ -99,7 +101,23 @@ static ScanIterator getIterator(ScanStreamReq request, HgStoreWrapperEx wrapper) if (selects != null) { properties = selects.getPropertiesList(); } - iter = new SelectIterator(iter, properties); + if (properties != null && !properties.isEmpty()) { + boolean isVertex = HugeServerTables.VERTEX_TABLE.equals(table) || + HugeServerTables.TASK_TABLE.equals(table); + try { + if (!isVertex && !HugeServerTables.isEdgeTable(table)) { + throw new IllegalArgumentException("Property selection requires a vertex or edge table: " + table); + } + iter = new SelectIterator(iter, properties, BusinessHandlerImpl.getGraphSupplier(graph), isVertex); + } catch (RuntimeException failure) { + try { + iter.close(); + } catch (RuntimeException closeFailure) { + failure.addSuppressed(closeFailure); + } + throw failure; + } + } iter.seek(request.getPosition().toByteArray()); return iter; } diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/QueryUtil.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/QueryUtil.java index 5d961038e6..c6fbbeed23 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/QueryUtil.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/QueryUtil.java @@ -42,6 +42,7 @@ import org.apache.hugegraph.store.grpc.query.AggregationType; import org.apache.hugegraph.store.grpc.query.DeDupOption; import org.apache.hugegraph.store.grpc.query.QueryRequest; +import org.apache.hugegraph.store.grpc.query.QueryResultFormat; import org.apache.hugegraph.store.grpc.query.ScanType; import org.apache.hugegraph.store.grpc.query.ScanTypeParam; import org.apache.hugegraph.store.node.grpc.EmptyIterator; @@ -100,12 +101,12 @@ public static QueryPlan buildPlan(QueryRequest request) { } else { if (request.getCheckTtl()) { var ttl = QueryStages.ofTtlCheckStage(); - ttl.init(isVertex(request.getTable())); + ttl.init(isVertex(request.getTable()), getGraphSupplier(request.getGraph())); plan.addStage(ttl); } // when to de-serialization ? - if (needDeserialize(request)) { + if (QueryResultFormat.requiresElementDeserialization(request)) { var deserializeStage = QueryStages.ofDeserializationStage(); deserializeStage.init(request.getTable(), getGraphSupplier(request.getGraph())); @@ -196,18 +197,6 @@ private static boolean canOptimiseToTop(QueryRequest request) { request.getLimit() > 0; } - /** - * Determine whether deserialization is needed. - * - * @param request query request object. - * @return true if deserialization is needed, false otherwise. - */ - private static boolean needDeserialize(QueryRequest request) { - return !isEmpty(request.getOrderByList()) || !isEmpty(request.getPropertyList()) - || !request.getCondition().isEmpty() || !isEmpty(request.getFunctionsList()) - && !request.getGroupBySchemaLabel(); - } - /** * Get a scan iterator. * @@ -295,14 +284,14 @@ public static BaseElement parseEntry(HugeGraphSupplier graph, BackendColumn column, boolean isVertex) { if (isVertex) { - return serializer.parseVertex(graph, column, null); + return serializer.parseSchemaVertex(graph, column, null); } else { - return serializer.parseEdge(graph, column, null, true); + return serializer.parseSchemaEdge(graph, column, null, true); } } - public static BaseElement parseOlap(BackendColumn column, BaseVertex vertex) { - return serializer.parseVertexOlap(null, column, vertex); + public static BaseElement parseOlap(HugeGraphSupplier graph, BackendColumn column, BaseVertex vertex) { + return serializer.parseSchemaVertexOlap(graph, column, vertex); } /** @@ -312,9 +301,13 @@ public static BaseElement parseOlap(BackendColumn column, BaseVertex vertex) { * @param olap olap vertex * @return new vertex */ - public static BackendColumn combineColumn(BackendColumn vertexColumn, + public static BackendColumn combineColumn(HugeGraphSupplier graph, BackendColumn vertexColumn, List olap) { - return serializer.mergeCols(vertexColumn, olap.toArray(new BackendColumn[0])); + BaseVertex vertex = serializer.parseSchemaVertex(graph, vertexColumn, null); + for (BackendColumn column : olap) { + serializer.parseSchemaVertexOlap(graph, column, vertex); + } + return BackendColumn.of(vertexColumn.name, serializer.formatSchemaVertexValue(vertex)); } public static AggregationFunction createFunc(AggregationType funcType, String genericType) { diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/OlapStage.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/OlapStage.java index a3dc6edd40..f9377d8f3d 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/OlapStage.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/OlapStage.java @@ -22,13 +22,16 @@ import java.util.ArrayList; import java.util.List; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.pd.common.PartitionUtils; import org.apache.hugegraph.rocksdb.access.RocksDBSession; import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.serializer.OlapKey; import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.store.business.BusinessHandler; +import org.apache.hugegraph.store.business.BusinessHandlerImpl; import org.apache.hugegraph.store.node.grpc.query.QueryStage; import org.apache.hugegraph.store.node.grpc.query.QueryUtil; import org.apache.hugegraph.store.node.grpc.query.model.PipelineResult; @@ -45,15 +48,25 @@ @Slf4j public class OlapStage implements QueryStage { - private final BusinessHandler handler = new QueryUtil().getHandler(); + private final BusinessHandler handler; private final BinaryElementSerializer serializer = new BinaryElementSerializer(); private String graph; + private HugeGraphSupplier supplier; private String table; private List properties; + public OlapStage() { + this(new QueryUtil().getHandler()); + } + + public OlapStage(BusinessHandler handler) { + this.handler = java.util.Objects.requireNonNull(handler, "handler"); + } + @Override public void init(Object... objects) { this.graph = (String) objects[0]; + this.supplier = BusinessHandlerImpl.getGraphSupplier(this.graph); this.table = (String) objects[1]; this.properties = QueryUtil.fromStringBytes((List) objects[2]); } @@ -70,32 +83,28 @@ public PipelineResult handle(PipelineResult result) { PartitionUtils.calcHashcode(BinaryElementSerializer.ownerId(element).asBytes()); for (Id property : properties) { - // Build key - var key = getOlapKey(property, element.id()); - var values = handler.doGet(this.graph, code, OLAP_TABLE, key); - if (values != null) { - var column = BackendColumn.of(key, values); - QueryUtil.parseOlap(column, (BaseVertex) element); + BackendColumn column = this.readProperty(code, property, element.id()); + if (column != null) { + QueryUtil.parseOlap(this.supplier, column, (BaseVertex) element); } } } else if (result.getResultType() == PipelineResultType.BACKEND_COLUMN) { var column = result.getColumn(); try { var vertexOnlyId = - serializer.parseVertex(null, BackendColumn.of(column.name, null), null); + serializer.parseSchemaVertex(this.supplier, BackendColumn.of(column.name, null), null); var code = PartitionUtils.calcHashcode( BinaryElementSerializer.ownerId(vertexOnlyId).asBytes()); // todo: Wait for structure to change to byte[] operations var list = new ArrayList(); for (Id property : properties) { - var key = getOlapKey(property, vertexOnlyId.id()); - var values = handler.doGet(this.graph, code, OLAP_TABLE, key); - if (values != null) { - list.add(BackendColumn.of(key, values)); + BackendColumn olap = this.readProperty(code, property, vertexOnlyId.id()); + if (olap != null) { + list.add(olap); } } var vertex = - QueryUtil.combineColumn(BackendColumn.of(column.name, column.value), list); + QueryUtil.combineColumn(this.supplier, BackendColumn.of(column.name, column.value), list); result.setColumn(RocksDBSession.BackendColumn.of(vertex.name, vertex.value)); } catch (Exception e) { log.error("parse olap error, graph: {}, table : {}", graph, table, e); @@ -105,11 +114,18 @@ public PipelineResult handle(PipelineResult result) { return result; } - private byte[] getOlapKey(Id propertyId, Id vertexId) { - BytesBuffer bufferName = - BytesBuffer.allocate(1 + propertyId.length() + 1 + vertexId.length()); - bufferName.writeId(propertyId); - return bufferName.writeId(vertexId).bytes(); + private BackendColumn readProperty(int code, Id propertyId, Id vertexId) { + byte[] key = OlapKey.format(propertyId, vertexId); + byte[] value = this.handler.doGet(this.graph, code, OLAP_TABLE, key); + if (value == null || value.length == 0) { + // Previous HStore writes used the standalone vertex-only key in the merged table. + byte[] legacyKey = BytesBuffer.allocate(vertexId.length() + 9).writeId(vertexId).bytes(); + value = this.handler.doGet(this.graph, code, OLAP_TABLE, legacyKey); + } + if (!OlapKey.matchesProperty(value, propertyId)) { + return null; + } + return BackendColumn.of(key, value); } @Override diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/TtlCheckStage.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/TtlCheckStage.java index 315ec2d31d..0185d52b13 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/TtlCheckStage.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/query/stages/TtlCheckStage.java @@ -17,6 +17,7 @@ package org.apache.hugegraph.store.node.grpc.query.stages; +import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.serializer.DirectBinarySerializer; import org.apache.hugegraph.store.node.grpc.query.QueryStage; import org.apache.hugegraph.store.node.grpc.query.model.PipelineResult; @@ -31,6 +32,7 @@ public class TtlCheckStage implements QueryStage { private boolean isVertex; + private HugeGraphSupplier graph; private final DirectBinarySerializer serializer = new DirectBinarySerializer(); private long now; @@ -38,6 +40,7 @@ public class TtlCheckStage implements QueryStage { @Override public void init(Object... objects) { this.isVertex = (boolean) objects[0]; + this.graph = (HugeGraphSupplier) objects[1]; now = System.currentTimeMillis(); } @@ -46,8 +49,8 @@ public PipelineResult handle(PipelineResult result) { if (result.getResultType() == PipelineResultType.BACKEND_COLUMN) { var col = result.getColumn(); try { - var element = isVertex ? serializer.parseVertex(col.name, col.value) : - serializer.parseEdge(col.name, col.value); + var element = isVertex ? serializer.parseSchemaVertex(this.graph, col.name, col.value) : + serializer.parseSchemaEdge(this.graph, col.name, col.value); if (element.expiredTime() > 0 && element.expiredTime() < now) { return null; } diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/task/TTLCleaner.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/task/TTLCleaner.java index 6836fe20b7..6e40dc8ba2 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/task/TTLCleaner.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/task/TTLCleaner.java @@ -93,7 +93,6 @@ public class TTLCleaner implements Runnable { private ThreadPoolExecutor executor; private final Set failedPartitions = Sets.newConcurrentHashSet(); private final ScheduledFuture future; - private final String key = "HUGEGRAPH/hg/EXPIRED"; private final DirectBinarySerializer serializer = new DirectBinarySerializer(); @Autowired private HgStoreNodeService service; @@ -127,24 +126,27 @@ public void submit() { scheduler.submit(this); } - public BiFunction getJudge(String table) { + public BiFunction getJudge(String graph, String table) { try { switch (table) { case HugeServerTables.VERTEX_TABLE: return (key, value) -> { - DirectHugeElement el = serializer.parseVertex(key, value); + DirectHugeElement el = serializer.parseSchemaVertex( + BusinessHandlerImpl.getGraphSupplier(graph), key, value); return predicate(el); }; case HugeServerTables.OUT_EDGE_TABLE: case HugeServerTables.IN_EDGE_TABLE: return (key, value) -> { - DirectHugeElement el = serializer.parseEdge(key, value); + DirectHugeElement el = serializer.parseSchemaEdge( + BusinessHandlerImpl.getGraphSupplier(graph), key, value); return predicate(el); }; case HugeServerTables.INDEX_TABLE: return (key, value) -> { - DirectHugeElement el = serializer.parseIndex(key, value); + DirectHugeElement el = serializer.parseSchemaIndex( + BusinessHandlerImpl.getGraphSupplier(graph), key, value); return predicate(el); }; default: @@ -182,7 +184,7 @@ public void run() { config.setAuthority(DefaultPdProvider.name, DefaultPdProvider.authority); client = new KvClient(config); } - KResponse k = client.get(key); + KResponse k = client.get("HUGEGRAPH/" + appConfig.getPdCluster() + "/EXPIRED"); String g = k.getValue(); log.info("cleaner config:{}", jobConfig); @@ -290,7 +292,7 @@ private Runnable getTask( RocksDBSession session = handler.getSession(id); InnerKeyCreator keyCreator = handler.getKeyCreator(); SessionOperator op = session.sessionOp(); - BiFunction judge = getJudge(table); + BiFunction judge = getJudge(graph, table); scan = op.scan(table, keyCreator.getStartKey(id, graph), keyCreator.getEndKey(id, graph), diff --git a/hugegraph-store/hg-store-test/pom.xml b/hugegraph-store/hg-store-test/pom.xml index bf1bc6f30c..34e57864e0 100644 --- a/hugegraph-store/hg-store-test/pom.xml +++ b/hugegraph-store/hg-store-test/pom.xml @@ -258,6 +258,8 @@ **/PartitionEngineErrorTest.java **/BatchGraphIsolationTest.java **/GraphIDManagerTest.java + **/SchemaDriverTest.java + **/StoredRowIngressTest.java diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java new file mode 100644 index 0000000000..4ee35b1ca3 --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java @@ -0,0 +1,614 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.store.business; + +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import java.nio.ByteBuffer; +import java.util.Properties; +import java.util.Set; + +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.pd.grpc.Metapb; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.rocksdb.access.RocksDBSession; +import org.apache.hugegraph.rocksdb.access.ScanIterator; +import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.DirectBinarySerializer; +import org.apache.hugegraph.serializer.OlapKey; +import org.apache.hugegraph.store.client.query.QueryExecutor; +import org.apache.hugegraph.store.cmd.HgCmdClient; +import org.apache.hugegraph.store.cmd.HgCmdProcessor; +import org.apache.hugegraph.store.cmd.request.BatchPutRequest; +import org.apache.hugegraph.store.cmd.response.BatchPutResponse; +import org.apache.hugegraph.store.grpc.common.Kv; +import org.apache.hugegraph.store.grpc.query.QueryRequest; +import org.apache.hugegraph.store.grpc.query.QueryResultFormat; +import org.apache.hugegraph.store.grpc.query.ScanType; +import org.apache.hugegraph.store.HgStoreEngine; +import org.apache.hugegraph.store.node.grpc.query.QueryUtil; +import org.apache.hugegraph.store.node.grpc.query.model.PipelineResult; +import org.apache.hugegraph.store.node.grpc.query.stages.TtlCheckStage; +import org.apache.hugegraph.store.node.grpc.query.stages.OlapStage; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.store.util.HgStoreException; +import org.apache.hugegraph.structure.BaseElement; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.BaseEdge; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.builder.IndexBuilder; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.EdgeLabelType; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.type.define.WriteType; +import org.apache.hugegraph.util.Bytes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import com.google.protobuf.ByteString; + +public class StoredRowIngressTest { + + private static final String FIXTURE = "compatibility/2f827d6e8/core-rows.properties"; + private final BinaryElementSerializer serializer = new BinaryElementSerializer(); + private final DirectBinarySerializer directSerializer = new DirectBinarySerializer(); + private Properties rows; + private HugeGraphSupplier graph; + + @Before + public void setUp() throws Exception { + this.rows = new Properties(); + try (InputStream input = getClass().getClassLoader().getResourceAsStream(FIXTURE)) { + Assert.assertNotNull("Frozen baseline BinarySerializer rows must be present", input); + this.rows.load(input); + } + this.graph = Mockito.mock(HugeGraphSupplier.class); + Mockito.when(this.graph.configuration()).thenReturn(new HugeConfig(Map.of())); + property(1, Cardinality.SINGLE, WriteType.OLTP); + property(2, Cardinality.LIST, WriteType.OLTP); + property(3, Cardinality.SET, WriteType.OLTP); + property(9, Cardinality.SINGLE, WriteType.OLAP_COMMON); + property(16, DataType.LONG, Cardinality.SINGLE, WriteType.OLTP); + property(17, DataType.TEXT, Cardinality.SINGLE, WriteType.OLTP); + VertexLabel vertex = new VertexLabel(this.graph, id(4), "person"); + vertex.properties(Set.of(id(1), id(2), id(3))); + vertex.ttl(60_000L); + Mockito.when(this.graph.vertexLabelOrNone(id(4))).thenReturn(vertex); + Mockito.when(this.graph.vertexLabel(id(4))).thenReturn(vertex); + EdgeLabel edge = new EdgeLabel(this.graph, id(5), "knows"); + edge.properties(Set.of(id(1), id(2), id(3))); + edge.sourceLabel(id(4)); + edge.targetLabel(id(4)); + edge.frequency(Frequency.MULTIPLE); + edge.ttl(60_000L); + Mockito.when(this.graph.edgeLabelOrNone(id(5))).thenReturn(edge); + Mockito.when(this.graph.edgeLabel(id(5))).thenReturn(edge); + index(6, IndexType.SECONDARY); + index(7, IndexType.RANGE_INT); + index(8, IndexType.RANGE_LONG); + index(15, IndexType.SECONDARY); + } + + @Test + public void testFilterIteratorReadsFrozenServerVertexAndEdges() { + for (String row : List.of("vertex", "edge.out", "edge.in")) { + BackendColumn column = column(row); + RocksDBSession.BackendColumn stored = RocksDBSession.BackendColumn.of(column.name, column.value); + ConditionQuery condition = new ConditionQuery(row.equals("vertex") ? HugeType.VERTEX : HugeType.EDGE); + condition.query(Condition.eq(id(1), 7)); + FilterIterator iterator = new FilterIterator<>(iterator(stored), condition, this.graph); + Assert.assertTrue(row, iterator.hasNext()); + Assert.assertSame(stored, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + iterator.close(); + + ConditionQuery noMatch = new ConditionQuery(condition.resultType()); + noMatch.query(Condition.eq(id(1), 8)); + FilterIterator rejected = new FilterIterator<>(iterator(stored), noMatch, this.graph); + Assert.assertFalse(row, rejected.hasNext()); + rejected.close(); + } + } + + @Test + public void testSchemaLookupFailureClosesAlreadyOpenedFilterIterator() { + ScanIterator source = Mockito.mock(ScanIterator.class); + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.query(Condition.eq(id(1), 7)); + HgStoreEngine engine = HgStoreEngine.getInstance(); + boolean previousClosing = engine.isClosing().getAndSet(false); + try { + FilterIterator.of(source, query.bytes(), "invalid-namespace"); + Assert.fail("Malformed metadata namespace must fail initialization"); + } catch (HgStoreException expected) { + Assert.assertTrue(expected.getMessage().contains("Graph must include")); + Mockito.verify(source).close(); + } finally { + engine.isClosing().set(previousClosing); + } + } + + @Test + public void testSelectionCountsActualMatchesAndPreservesCollectionsAndTtl() { + for (String row : List.of("vertex", "edge.out", "edge.in")) { + BackendColumn column = column(row); + RocksDBSession.BackendColumn stored = RocksDBSession.BackendColumn.of(column.name, column.value); + boolean isVertex = row.equals("vertex"); + // Requested count equals stored count, but one requested ID is absent. + SelectIterator iterator = new SelectIterator(iterator(stored), List.of(2, 3, 99), + this.graph, isVertex); + RocksDBSession.BackendColumn selected = iterator.next(); + Assert.assertArrayEquals(stored.name, selected.name); + BaseElement element = QueryUtil.parseEntry(this.graph, + BackendColumn.of(selected.name, selected.value), isVertex); + Assert.assertEquals(2, element.sizeOfProperties()); + Assert.assertEquals(List.of(7, -1, 7), element.getPropertyValue(id(2))); + Assert.assertEquals(Set.of(-1, 7), element.getPropertyValue(id(3))); + Assert.assertNull(element.getPropertyValue(id(1))); + Assert.assertEquals(expiry(), element.expiredTime()); + iterator.close(); + } + } + + @Test + public void testSelectionOfMissingPropertiesWritesZeroCountAndKeepsTtl() { + BackendColumn column = column("vertex"); + RocksDBSession.BackendColumn stored = RocksDBSession.BackendColumn.of(column.name, column.value); + SelectIterator iterator = new SelectIterator(iterator(stored), List.of(99), this.graph, true); + RocksDBSession.BackendColumn selected = iterator.next(); + BaseVertex vertex = this.serializer.parseSchemaVertex(this.graph, + BackendColumn.of(selected.name, selected.value), null); + Assert.assertEquals(0, vertex.sizeOfProperties()); + Assert.assertEquals(expiry(), vertex.expiredTime()); + iterator.close(); + } + + @Test + public void testOlapMergeKeepsPersistentSchemaFormatAndTtl() { + BackendColumn merged = QueryUtil.combineColumn(this.graph, column("vertex"), List.of(column("olap"))); + BaseVertex vertex = this.serializer.parseSchemaVertex(this.graph, merged, null); + Assert.assertEquals(4, vertex.sizeOfProperties()); + Assert.assertEquals(Integer.valueOf(42), vertex.getPropertyValue(id(9))); + Assert.assertEquals(expiry(), vertex.expiredTime()); + } + + @Test + public void testDirectTtlReaderUsesFrozenRowSchemaAndIndexNameSuffix() { + BackendColumn vertex = column("vertex"); + Assert.assertEquals(expiry(), this.directSerializer.parseSchemaVertex( + this.graph, vertex.name, vertex.value).expiredTime()); + for (String row : List.of("edge.out", "edge.in")) { + BackendColumn edge = column(row); + Assert.assertEquals(expiry(), this.directSerializer.parseSchemaEdge( + this.graph, edge.name, edge.value).expiredTime()); + } + for (String row : List.of("index.secondary", "index.int", "index.long")) { + BackendColumn index = column(row); + Assert.assertEquals(expiry(), this.directSerializer.parseSchemaIndex( + this.graph, index.name, index.value).expiredTime()); + Assert.assertEquals(expiry(), this.serializer.parseSchemaIndex(this.graph, index).expiredTime()); + } + } + + @Test + public void testTtlPipelineAcceptsLiveFixtureAndRejectsExpiredFixture() throws Exception { + Field now = TtlCheckStage.class.getDeclaredField("now"); + now.setAccessible(true); + for (String row : List.of("vertex", "edge.out", "edge.in")) { + TtlCheckStage stage = new TtlCheckStage(); + stage.init(row.equals("vertex"), this.graph); + BackendColumn column = column(row); + PipelineResult input = new PipelineResult(RocksDBSession.BackendColumn.of(column.name, column.value)); + now.setLong(stage, Long.parseLong(this.rows.getProperty("now"))); + Assert.assertSame(row, input, stage.handle(input)); + now.setLong(stage, expiry() + 1); + Assert.assertNull(row, stage.handle(input)); + } + } + + @Test + public void testClientDecodesPersistentRowsAndTaggedElementResponsesExplicitly() throws Exception { + QueryExecutor executor = new QueryExecutor(null, this.graph, 60_000L); + Method decode = QueryExecutor.class.getDeclaredMethod("fromKv", String.class, Kv.class, + boolean.class, boolean.class); + decode.setAccessible(true); + BackendColumn stored = column("vertex"); + BaseVertex persistent = (BaseVertex) decode.invoke(executor, "g+v", kv(stored), false, true); + Assert.assertNotNull(persistent); + Assert.assertEquals(List.of(7, -1, 7), persistent.getPropertyValue(id(2))); + BackendColumn tagged = this.serializer.writeVertex(persistent); + BaseVertex response = (BaseVertex) decode.invoke(executor, "g+v", kv(tagged), false, false); + Assert.assertNotNull(response); + Set expectedGroups = persistent.getPropertyValue(id(3)); + Set actualGroups = response.getPropertyValue(id(3)); + Assert.assertEquals(expectedGroups, actualGroups); + Assert.assertEquals(expiry(), response.expiredTime()); + } + + @Test + public void testUntimedAndSystemRowsDoNotRequireTrailingTtl() { + VertexLabel untimed = new VertexLabel(this.graph, id(10), "untimed"); + untimed.properties(Set.of(id(1), id(2), id(3))); + Mockito.when(this.graph.vertexLabel(id(10))).thenReturn(untimed); + Mockito.when(this.graph.vertexLabelOrNone(id(10))).thenReturn(untimed); + EdgeLabel edge = new EdgeLabel(this.graph, id(11), "untimedEdge"); + edge.properties(Set.of(id(1), id(2), id(3))); + edge.sourceLabel(id(4)); + edge.targetLabel(id(4)); + edge.frequency(Frequency.MULTIPLE); + Mockito.when(this.graph.edgeLabel(id(11))).thenReturn(edge); + Mockito.when(this.graph.edgeLabelOrNone(id(11))).thenReturn(edge); + for (int number : List.of(12, 13, 14)) { + IndexLabel label = new IndexLabel(this.graph, id(number), "untimedIndex" + number); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(id(10)); + label.indexType(number == 12 ? IndexType.SECONDARY : + number == 13 ? IndexType.RANGE_INT : IndexType.RANGE_LONG); + label.indexFields(id(number == 12 ? 17 : number == 13 ? 1 : 16)); + Mockito.when(this.graph.indexLabel(id(number))).thenReturn(label); + } + BackendColumn vertex = column("vertex.untimed"); + Assert.assertEquals(0L, this.serializer.parseSchemaVertex(this.graph, vertex, null).expiredTime()); + BackendColumn untimedEdge = column("edge.untimed"); + Assert.assertEquals(0L, this.serializer.parseSchemaEdge(this.graph, untimedEdge, null, true).expiredTime()); + for (String row : List.of("index.secondary.untimed", "index.int.untimed", "index.long.untimed", + "index.system")) { + BackendColumn column = column(row); + Assert.assertEquals(row, 0L, this.serializer.parseSchemaIndex(this.graph, column).expiredTime()); + Assert.assertEquals(row, 0L, this.directSerializer.parseSchemaIndex( + this.graph, column.name, column.value).expiredTime()); + } + } + + @Test + public void testRebuiltIndexWriterMatchesFrozenServerColumnsAndStoreReader() { + BaseVertex vertex = this.serializer.parseSchemaVertex(this.graph, column("vertex"), null); + vertex.addProperty(this.graph.propertyKey(id(16)), 7L); + vertex.addProperty(this.graph.propertyKey(id(17)), "alice"); + IndexBuilder builder = new IndexBuilder(this.graph); + Map fixtures = Map.of(6, "index.secondary", 7, "index.int", 8, "index.long"); + for (Map.Entry fixture : fixtures.entrySet()) { + List indexes = builder.buildIndex(vertex, this.graph.indexLabel(id(fixture.getKey()))); + Assert.assertEquals(1, indexes.size()); + assertPersistentIndex(indexes.get(0), fixture.getValue()); + } + vertex.addProperty(this.graph.propertyKey(id(17)), "long-field-".repeat(20)); + List longString = builder.buildIndex(vertex, this.graph.indexLabel(id(15))); + Assert.assertEquals(1, longString.size()); + assertPersistentIndex(longString.get(0), "index.hashed"); + } + + @Test + public void testSchemaIndexWriterHashingMatchesFrozenServerColumn() { + // Also verify hashing at the serializer boundary without depending on the builder. + // The frozen Server producer supplies the same complete field value. + Index index = new Index(this.graph, this.graph.indexLabel(id(15)), true); + index.fieldValues("long-field-".repeat(20)); + index.elementIds(id(1), expiry()); + assertPersistentIndex(index, "index.hashed"); + } + + @Test + public void testStringIndexBranchesPreserveLongValuesAndCanonicalEscapes() { + BaseVertex vertex = this.serializer.parseSchemaVertex(this.graph, column("vertex"), null); + IndexBuilder builder = new IndexBuilder(this.graph); + String longValue = "long-field-".repeat(20); + for (IndexType type : List.of(IndexType.SECONDARY, IndexType.SHARD, IndexType.UNIQUE)) { + IndexLabel label = new IndexLabel(this.graph, id(20), "stringIndex"); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(id(4)); + label.indexType(type); + label.indexFields(id(17)); + vertex.addProperty(this.graph.propertyKey(id(17)), longValue); + Assert.assertEquals(type.name(), longValue, builder.buildIndex(vertex, label).get(0).fieldValues()); + vertex.addProperty(this.graph.propertyKey(id(17)), ""); + Assert.assertEquals(type.name(), "\u0002", builder.buildIndex(vertex, label).get(0).fieldValues()); + vertex.addProperty(this.graph.propertyKey(id(17)), "prefix!tail"); + Assert.assertEquals(type.name(), "prefix`!tail", builder.buildIndex(vertex, label).get(0).fieldValues()); + vertex.addProperty(this.graph.propertyKey(id(17)), "\u0001illegal"); + try { + builder.buildIndex(vertex, label); + Assert.fail("Reserved leading index symbols must remain illegal: " + type); + } catch (IllegalArgumentException expected) { + Assert.assertTrue(expected.getMessage().contains("Illegal leading char")); + } + } + } + + @Test + public void testUniqueNullableFieldUsesCanonicalNullSentinel() { + property(18, DataType.TEXT, Cardinality.SINGLE, WriteType.OLTP); + this.graph.vertexLabel(id(4)).nullableKeys(id(18)); + BaseVertex vertex = this.serializer.parseSchemaVertex(this.graph, column("vertex"), null); + vertex.addProperty(this.graph.propertyKey(id(17)), "prefix"); + IndexLabel label = new IndexLabel(this.graph, id(21), "nullableUnique"); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(id(4)); + label.indexType(IndexType.UNIQUE); + label.indexFields(id(17), id(18)); + List indexes = new IndexBuilder(this.graph).buildIndex(vertex, label); + Assert.assertEquals(1, indexes.size()); + Assert.assertEquals("prefix!\u0001", indexes.get(0).fieldValues()); + } + + @Test + public void testFrozenLegacyStoreTtlEnvelopeRemainsReadable() throws Exception { + Properties legacy = new Properties(); + try (InputStream input = getClass().getClassLoader().getResourceAsStream( + "compatibility/2f827d6e8/store-index-rows.properties")) { + Assert.assertNotNull("Frozen baseline Store index writer output must be present", input); + legacy.load(input); + } + for (String row : List.of("secondary", "int", "long", "system")) { + BackendColumn column = BackendColumn.of(Bytes.fromHex(legacy.getProperty(row + ".name")), + Bytes.fromHex(legacy.getProperty(row + ".value"))); + long expectedExpiry = Long.parseLong(legacy.getProperty(row + ".expiry")); + Assert.assertEquals(row, expectedExpiry, + this.serializer.parseSchemaIndex(this.graph, column).expiredTime()); + Assert.assertEquals(row, expectedExpiry, this.directSerializer.parseSchemaIndex( + this.graph, column.name, column.value).expiredTime()); + } + } + + @Test + public void testOlapStageReadsFrozenLegacyRowsWithoutCrossPropertyLeakage() throws Exception { + property(18, Cardinality.SINGLE, WriteType.OLAP_COMMON); + BackendColumn legacy = column("olap"); + Map rows = new HashMap<>(); + rows.put(ByteBuffer.wrap(legacy.name), legacy.value); + for (boolean tagged : List.of(false, true)) { + BaseVertex merged = runOlapStage(rows, tagged, id(9), id(18)); + Assert.assertEquals(42, (Object) merged.getProperty(id(9)).value()); + Assert.assertNull(merged.getProperty(id(18))); + Assert.assertArrayEquals(legacy.value, rows.get(ByteBuffer.wrap(legacy.name))); + Assert.assertEquals(1, rows.size()); + } + } + + @Test + public void testOlapStageMergesMultiplePropertiesAndPrefersNamespacedValues() throws Exception { + property(18, Cardinality.SINGLE, WriteType.OLAP_COMMON); + BackendColumn legacy = column("olap"); + Map rows = new HashMap<>(); + rows.put(ByteBuffer.wrap(legacy.name), legacy.value); + rows.put(ByteBuffer.wrap(OlapKey.format(id(9), id(1))), schemaOlapValue(id(9), 99)); + rows.put(ByteBuffer.wrap(OlapKey.format(id(18), id(1))), schemaOlapValue(id(18), 123)); + for (boolean tagged : List.of(false, true)) { + BaseVertex merged = runOlapStage(rows, tagged, id(9), id(18)); + Assert.assertEquals(99, (Object) merged.getProperty(id(9)).value()); + Assert.assertEquals(123, (Object) merged.getProperty(id(18)).value()); + Assert.assertArrayEquals(legacy.value, rows.get(ByteBuffer.wrap(legacy.name))); + } + } + + private byte[] schemaOlapValue(Id property, int value) { + BaseVertex vertex = new BaseVertex(id(1), VertexLabel.OLAP_VL); + vertex.addProperty(this.graph.propertyKey(property), value); + BytesBuffer buffer = BytesBuffer.allocate(16); + this.serializer.formatSchemaProperty(vertex.getProperty(property), buffer); + return buffer.bytes(); + } + + private BaseVertex runOlapStage(Map rows, boolean tagged, Id... properties) throws Exception { + String graphName = "CODEC_TEST/olap/g"; + BusinessHandler handler = Mockito.mock(BusinessHandler.class); + Mockito.when(handler.doGet(Mockito.eq(graphName), Mockito.anyInt(), Mockito.eq("g+olap"), + Mockito.any(byte[].class))).thenAnswer(call -> + rows.get(ByteBuffer.wrap(call.getArgument(3)))); + Field mock = BusinessHandlerImpl.class.getDeclaredField("mockGraphSupplier"); + mock.setAccessible(true); + HugeGraphSupplier previous = (HugeGraphSupplier) mock.get(null); + BusinessHandlerImpl.setMockGraphSupplier(this.graph); + OlapStage stage = new OlapStage(handler); + try { + List requested = new ArrayList<>(); + for (Id property : properties) { + requested.add(ByteString.copyFrom(BytesBuffer.allocate(16).writeId(property).bytes())); + } + stage.init(graphName, "g+v", requested); + BackendColumn vertex = column("vertex"); + BaseVertex decoded = this.serializer.parseSchemaVertex(this.graph, vertex, null); + PipelineResult input = tagged ? new PipelineResult(decoded) : + new PipelineResult(RocksDBSession.BackendColumn.of(vertex.name, vertex.value)); + Assert.assertSame(input, stage.handle(input)); + if (tagged) { + return (BaseVertex) input.getElement(); + } + return this.serializer.parseSchemaVertex(this.graph, + BackendColumn.of(input.getColumn().name, input.getColumn().value), null); + } finally { + stage.close(); + BusinessHandlerImpl.setMockGraphSupplier(previous); + } + } + + private void assertPersistentIndex(Index rebuilt, String fixture) { + BackendColumn expected = column(fixture); + BackendColumn written = this.serializer.writeSchemaIndex(rebuilt); + // DataManager's persisted batch normalizes an absent payload to zero bytes. + byte[] value = written.value == null ? new byte[0] : written.value; + Assert.assertArrayEquals(fixture, expected.name, written.name); + Assert.assertArrayEquals(fixture, expected.value, value); + Index decoded = this.serializer.parseSchemaIndex(this.graph, BackendColumn.of(written.name, value)); + Assert.assertEquals(rebuilt.elementId(), decoded.elementId()); + Assert.assertEquals(rebuilt.fieldValues(), decoded.fieldValues()); + Assert.assertEquals(expiry(), decoded.expiredTime()); + } + + @Test + public void testParentRequestedRebuildIndexesChildRowsAndExcludesUnrelatedLabels() throws Exception { + EdgeLabel parent = new EdgeLabel(this.graph, id(100), "parent"); + EdgeLabel child = new EdgeLabel(this.graph, id(101), "child"); + child.edgeLabelType(EdgeLabelType.SUB); + child.fatherId(parent.id()); + EdgeLabel unrelated = new EdgeLabel(this.graph, id(102), "unrelated"); + for (EdgeLabel label : List.of(parent, child, unrelated)) { + label.properties(Set.of(id(17))); + // Real sublabels persist their own endpoint links; they do not inherit them on read. + label.sourceLabel(id(4)); + label.targetLabel(id(4)); + Assert.assertEquals(id(4), label.sourceLabel()); + Assert.assertEquals(id(4), label.targetLabel()); + Mockito.when(this.graph.edgeLabel(label.id())).thenReturn(label); + Mockito.when(this.graph.edgeLabelOrNone(label.id())).thenReturn(label); + } + IndexLabel index = new IndexLabel(this.graph, id(103), "parentIndex"); + index.baseType(HugeType.EDGE_LABEL); + index.baseValue(parent.id()); + index.indexType(IndexType.SECONDARY); + index.indexFields(id(17)); + Mockito.when(this.graph.indexLabel(index.id())).thenReturn(index); + BaseEdge childEdge = new BaseEdge(new EdgeId(id(1), Directions.OUT, parent.id(), child.id(), "", id(2)), child); + childEdge.isOutEdge(true); + childEdge.addProperty(this.graph.propertyKey(id(17)), "child record"); + BaseEdge otherEdge = new BaseEdge(new EdgeId(id(3), Directions.OUT, unrelated.id(), unrelated.id(), "", id(4)), + unrelated); + otherEdge.isOutEdge(true); + otherEdge.addProperty(this.graph.propertyKey(id(17)), "unrelated record"); + ScanIterator source = Mockito.mock(ScanIterator.class); + Mockito.when(source.hasNext()).thenReturn(true, true, false); + Mockito.when(source.next()).thenReturn(rebuildInput(childEdge), rebuildInput(otherEdge)); + BusinessHandler handler = Mockito.mock(BusinessHandler.class); + String graphName = "CODEC_TEST/rebuild/g"; + Mockito.when(handler.scan(graphName, "g+oe", 0, 65536)).thenReturn(source); + List written = new ArrayList<>(); + HgCmdClient client = Mockito.mock(HgCmdClient.class); + Mockito.when(client.batchPut(Mockito.any(BatchPutRequest.class))).thenAnswer(call -> { + BatchPutRequest request = call.getArgument(0); + written.addAll(request.getEntries()); + BatchPutResponse response = new BatchPutResponse(); + response.setStatus(HgCmdProcessor.Status.OK); + return response; + }); + DataManagerImpl manager = new DataManagerImpl(); + manager.setBusinessHandler(handler); + manager.setCmdClient(client); + Metapb.BuildIndexParam request = Metapb.BuildIndexParam.newBuilder().setGraph(graphName) + .setLabelId(ByteString.copyFrom(BytesBuffer.allocate(8).writeId(parent.id()).bytes())) + .setIsVertexLabel(false) + .setIndexLabel(ByteString.copyFrom(BytesBuffer.allocate(8).writeId(index.id()).bytes())).build(); + Metapb.Partition partition = Metapb.Partition.newBuilder().setId(9999).setStartKey(0).setEndKey(65536).build(); + Field mock = BusinessHandlerImpl.class.getDeclaredField("mockGraphSupplier"); + mock.setAccessible(true); + HugeGraphSupplier previous = (HugeGraphSupplier) mock.get(null); + BusinessHandlerImpl.setMockGraphSupplier(this.graph); + try { + Assert.assertTrue(manager.doBuildIndex(request, partition).isOk()); + Assert.assertEquals(1, written.size()); + BatchPutRequest.KV row = written.get(0); + Index decoded = this.serializer.parseSchemaIndex(this.graph, + BackendColumn.of(row.getKey(), row.getValue())); + Assert.assertEquals(parent.id(), decoded.indexLabel().baseValue()); + Assert.assertEquals(childEdge.id(), decoded.elementId()); + Assert.assertEquals("child record", decoded.fieldValues()); + Mockito.verify(source).close(); + } finally { + BusinessHandlerImpl.setMockGraphSupplier(previous); + } + } + + private RocksDBSession.BackendColumn rebuildInput(BaseEdge edge) { + byte[] name = this.serializer.formatEdgeName(edge); + // Range scans remove the graph prefix but retain the physical hash-code suffix. + return RocksDBSession.BackendColumn.of(Arrays.copyOf(name, name.length + Short.BYTES), + this.serializer.formatSchemaEdgeValue(edge)); + } + + @Test + public void testResponseFormatMatchesDeserializationPlanning() { + QueryRequest.Builder request = QueryRequest.newBuilder().setScanType(ScanType.TABLE_SCAN); + Assert.assertFalse(QueryResultFormat.returnsTaggedElements(request.build())); + request.setCheckTtl(true); + Assert.assertFalse(QueryResultFormat.returnsTaggedElements(request.build())); + request.addProperty(ByteString.copyFromUtf8("property")); + Assert.assertTrue(QueryResultFormat.requiresElementDeserialization(request.build())); + Assert.assertTrue(QueryResultFormat.returnsTaggedElements(request.build())); + request.clearProperty().addOrderBy(ByteString.copyFromUtf8("order")); + Assert.assertTrue(QueryResultFormat.returnsTaggedElements(request.build())); + request.clearOrderBy().setCondition(ByteString.copyFromUtf8("condition")); + Assert.assertTrue(QueryResultFormat.returnsTaggedElements(request.build())); + } + + private void property(int value, Cardinality cardinality, WriteType writeType) { + property(value, DataType.INT, cardinality, writeType); + } + + private void property(int value, DataType type, Cardinality cardinality, WriteType writeType) { + PropertyKey key = new PropertyKey(this.graph, id(value), "property" + value); + key.dataType(type); + key.cardinality(cardinality); + key.writeType(writeType); + Mockito.when(this.graph.propertyKey(id(value))).thenReturn(key); + } + + private void index(int value, IndexType type) { + IndexLabel label = new IndexLabel(this.graph, id(value), "index" + value); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(id(4)); + label.indexType(type); + label.indexFields(id(type == IndexType.RANGE_LONG ? 16 : type == IndexType.SECONDARY ? 17 : 1)); + Mockito.when(this.graph.indexLabel(id(value))).thenReturn(label); + } + + private BackendColumn column(String row) { + return BackendColumn.of(Bytes.fromHex(this.rows.getProperty(row + ".column.0.name")), + Bytes.fromHex(this.rows.getProperty(row + ".column.0.value"))); + } + + private long expiry() { + return Long.parseLong(this.rows.getProperty("expiry")); + } + + private static Id id(int value) { + return IdGenerator.of(value); + } + + private static Kv kv(BackendColumn column) { + return Kv.newBuilder().setKey(ByteString.copyFrom(column.name)) + .setValue(ByteString.copyFrom(column.value)).build(); + } + + private static ScanIterator iterator(RocksDBSession.BackendColumn column) { + ScanIterator iterator = Mockito.mock(ScanIterator.class); + Mockito.when(iterator.hasNext()).thenReturn(true, false); + Mockito.when(iterator.next()).thenReturn(column); + return iterator; + } +} diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/schema/SchemaDriverTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/schema/SchemaDriverTest.java new file mode 100644 index 0000000000..4040451427 --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/schema/SchemaDriverTest.java @@ -0,0 +1,548 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.store.schema; + +import java.lang.reflect.Field; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.exception.NotAllowException; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.pd.client.KvClient; +import org.apache.hugegraph.pd.client.PDConfig; +import org.apache.hugegraph.pd.common.PDException; +import org.apache.hugegraph.pd.grpc.kv.KResponse; +import org.apache.hugegraph.pd.grpc.kv.ScanPrefixResponse; +import org.apache.hugegraph.pd.grpc.kv.WatchEvent; +import org.apache.hugegraph.pd.grpc.kv.WatchKv; +import org.apache.hugegraph.pd.grpc.kv.WatchResponse; +import org.apache.hugegraph.pd.grpc.kv.WatchType; +import org.apache.hugegraph.store.HgStoreEngine; +import org.apache.hugegraph.store.business.BusinessHandlerImpl; +import org.apache.hugegraph.store.options.HgStoreEngineOptions; +import org.apache.hugegraph.store.util.HgStoreException; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.junit.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class SchemaDriverTest { + + private AtomicReference instance; + private SchemaDriver previousInstance; + + @Before + public void setUp() throws Exception { + this.instance = instanceReference(); + this.previousInstance = this.instance.getAndSet(null); + } + + @After + public void tearDown() { + this.instance.set(this.previousInstance); + } + + @Test + public void testDestroyClosesOwnedKvClient() { + TrackingKvClient client = new TrackingKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + + try { + SchemaDriver.destroy(); + + Assert.assertTrue(client.closed); + Assert.assertNull(SchemaDriver.getInstance()); + } finally { + client.close(); + } + } + + @Test + public void testDestroyUnpublishesInstanceBeforeClosingResources() throws Exception { + BlockingCloseKvClient client = new BlockingCloseKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + Thread destroyThread = new Thread(SchemaDriver::destroy, "schema-driver-destroy"); + try { + destroyThread.start(); + client.awaitCloseStarted(); + + Assert.assertNull(SchemaDriver.getInstance()); + } finally { + client.allowClose.countDown(); + destroyThread.join(5000L); + client.close(); + } + + Assert.assertFalse(destroyThread.isAlive()); + Assert.assertTrue(client.closed); + } + + @Test + public void testInitDoesNotWaitForDestroyCleanup() throws Exception { + BlockingCloseKvClient client = new BlockingCloseKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + AtomicReference initFailure = new AtomicReference<>(); + CountDownLatch initFinished = new CountDownLatch(1); + Thread destroyThread = new Thread(SchemaDriver::destroy, "schema-driver-destroy"); + Thread initThread = new Thread(() -> { + try { + SchemaDriver.init(PDConfig.of("127.0.0.1:8686"), 10, 60_000L); + } catch (Throwable throwable) { + initFailure.set(throwable); + } finally { + initFinished.countDown(); + } + }, "schema-driver-init"); + boolean initCompletedDuringCleanup; + try { + destroyThread.start(); + client.awaitCloseStarted(); + initThread.start(); + initCompletedDuringCleanup = initFinished.await(1L, TimeUnit.SECONDS); + } finally { + client.allowClose.countDown(); + destroyThread.join(5000L); + initThread.join(5000L); + client.close(); + } + + Assert.assertTrue(initCompletedDuringCleanup); + Assert.assertTrue(initFailure.get() instanceof NotAllowException); + Assert.assertFalse(destroyThread.isAlive()); + Assert.assertFalse(initThread.isAlive()); + } + + @Test + public void testConcurrentDestroyWaitsForCleanup() throws Exception { + BlockingCloseKvClient client = new BlockingCloseKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + CountDownLatch secondDestroyStarted = new CountDownLatch(1); + CountDownLatch secondDestroyReturned = new CountDownLatch(1); + Thread firstDestroy = new Thread(SchemaDriver::destroy, "schema-driver-destroy-first"); + Thread secondDestroy = new Thread(() -> { + secondDestroyStarted.countDown(); + SchemaDriver.destroy(); + secondDestroyReturned.countDown(); + }, "schema-driver-destroy-second"); + boolean returnedBeforeCleanup; + try { + firstDestroy.start(); + client.awaitCloseStarted(); + secondDestroy.start(); + Assert.assertTrue(secondDestroyStarted.await(5L, TimeUnit.SECONDS)); + returnedBeforeCleanup = secondDestroyReturned.await(500L, TimeUnit.MILLISECONDS); + } finally { + client.allowClose.countDown(); + firstDestroy.join(5000L); + secondDestroy.join(5000L); + client.close(); + } + + Assert.assertFalse(returnedBeforeCleanup); + Assert.assertFalse(firstDestroy.isAlive()); + Assert.assertFalse(secondDestroy.isAlive()); + } + + @Test + public void testConstructorFailureClosesOwnedKvClient() { + FailingListenKvClient client = new FailingListenKvClient(); + + try { + new SchemaDriver(client, 10, 60_000L); + Assert.fail("SchemaDriver construction should fail"); + } catch (HugeException expected) { + Assert.assertEquals(2, client.listenCalls); + Assert.assertTrue(client.closed); + } finally { + client.close(); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testStoreCleanupClosesDriverAndReleasesGraphWrappers() throws Exception { + Field cacheField = BusinessHandlerImpl.class.getDeclaredField("GRAPH_SUPPLIER_CACHE"); + cacheField.setAccessible(true); + Map cache = (Map) cacheField.get(null); + Map previousCache = new HashMap<>(cache); + HugeGraphSupplier supplier = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, args) -> null); + TrackingKvClient client = new TrackingKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + try { + cache.put("space/graph", supplier); + BusinessHandlerImpl.clearCache(); + Assert.assertTrue(cache.isEmpty()); + Assert.assertFalse(client.closed); + Assert.assertSame(driver, SchemaDriver.getInstance()); + + cache.put("space/graph", supplier); + BusinessHandlerImpl.closeSchemaResources(); + Assert.assertTrue(client.closed); + Assert.assertNull(SchemaDriver.getInstance()); + Assert.assertTrue(cache.isEmpty()); + BusinessHandlerImpl.closeSchemaResources(); + + TrackingKvClient replacementClient = new TrackingKvClient(); + this.instance.set(new SchemaDriver(replacementClient, 10, 60_000L)); + BusinessHandlerImpl.closeSchemaResources(); + Assert.assertTrue(replacementClient.closed); + } finally { + SchemaDriver.destroy(); + cache.putAll(previousCache); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testStoreCleanupReleasesWrappersWhenClientCloseFails() throws Exception { + Field cacheField = BusinessHandlerImpl.class.getDeclaredField("GRAPH_SUPPLIER_CACHE"); + cacheField.setAccessible(true); + Map cache = (Map) cacheField.get(null); + Map previousCache = new HashMap<>(cache); + HugeGraphSupplier supplier = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, args) -> null); + TrackingKvClient client = new TrackingKvClient() { + @Override + public void close() { + super.close(); + throw new IllegalStateException("close failed"); + } + }; + this.instance.set(new SchemaDriver(client, 10, 60_000L)); + try { + cache.put("space/graph", supplier); + try { + BusinessHandlerImpl.closeSchemaResources(); + Assert.fail("Client close failure must propagate"); + } catch (IllegalStateException expected) { + Assert.assertEquals("close failed", expected.getMessage()); + } + Assert.assertTrue(client.closed); + Assert.assertNull(SchemaDriver.getInstance()); + Assert.assertTrue(cache.isEmpty()); + BusinessHandlerImpl.closeSchemaResources(); + } finally { + SchemaDriver.destroy(); + cache.putAll(previousCache); + } + } + + @Test + public void testClosingStoreRejectsNewGraphSupplierWithoutOpeningPdClient() { + HgStoreEngine engine = HgStoreEngine.getInstance(); + boolean previousClosing = engine.isClosing().getAndSet(true); + try { + BusinessHandlerImpl.getGraphSupplier("schema-driver-test/closing"); + Assert.fail("Closing Store must reject schema client creation"); + } catch (HgStoreException expected) { + Assert.assertEquals("Store is closing", expected.getMessage()); + Assert.assertNull(SchemaDriver.getInstance()); + } finally { + engine.isClosing().set(previousClosing); + } + } + + @Test + public void testSchemaLookupCachesByIdAndNameAndWatchClearsOnlyTargetGraph() { + CachingKvClient client = new CachingKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + try { + Assert.assertEquals(4, client.listeners.size()); + PropertyKey first = driver.propertyKey("space", "graph", IdGenerator.of(1), null); + Assert.assertSame(first, driver.propertyKey("space", "graph", "name", null)); + PropertyKey other = driver.propertyKey("space", "other", IdGenerator.of(1), null); + Assert.assertEquals(2, client.getCalls); + + client.publish("HUGEGRAPH/hg/EVENT/GRAPH/SCHEMA/CLEAR", "space-graph"); + Assert.assertNotSame(first, driver.propertyKey("space", "graph", IdGenerator.of(1), null)); + Assert.assertSame(other, driver.propertyKey("space", "other", IdGenerator.of(1), null)); + Assert.assertEquals(3, client.getCalls); + } finally { + SchemaDriver.destroy(); + } + } + + @Test + public void testSchemaClearJsonFromServerEvictsOnlyNamedGraphAndKeepsLegacyFormat() { + CachingKvClient client = new CachingKvClient(); + SchemaDriver driver = new SchemaDriver(client, "alternate", 10, 60_000L); + this.instance.set(driver); + String eventKey = "HUGEGRAPH/alternate/EVENT/GRAPH/SCHEMA/CLEAR"; + try { + PropertyKey first = driver.propertyKey("space", "graph-with-hyphen", IdGenerator.of(1), null); + PropertyKey other = driver.propertyKey("space", "other", IdGenerator.of(1), null); + // Current Server CachedSchemaTransactionV2 publishes a source-bearing JSON event. + client.publish(eventKey, "{\"graph\":\"space-graph-with-hyphen\",\"source\":\"server-process-1\"}"); + PropertyKey refreshed = driver.propertyKey("space", "graph-with-hyphen", IdGenerator.of(1), null); + Assert.assertNotSame(first, refreshed); + Assert.assertSame(other, driver.propertyKey("space", "other", IdGenerator.of(1), null)); + Assert.assertEquals(3, client.getCalls); + + client.publish(eventKey, "space-graph-with-hyphen"); + Assert.assertNotSame(refreshed, + driver.propertyKey("space", "graph-with-hyphen", IdGenerator.of(1), null)); + Assert.assertSame(other, driver.propertyKey("space", "other", IdGenerator.of(1), null)); + Assert.assertEquals(4, client.getCalls); + } finally { + SchemaDriver.destroy(); + } + } + + @Test + public void testMalformedSchemaClearPayloadDoesNotInvalidateUnrelatedCaches() { + CachingKvClient client = new CachingKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + String eventKey = "HUGEGRAPH/hg/EVENT/GRAPH/SCHEMA/CLEAR"; + try { + PropertyKey cached = driver.propertyKey("space", "graph", IdGenerator.of(1), null); + for (String payload : new String[]{"{broken", "{\"source\":\"server-process-1\"}", "{\"graph\":null}"}) { + client.publish(eventKey, payload); + } + Assert.assertSame(cached, driver.propertyKey("space", "graph", IdGenerator.of(1), null)); + Assert.assertEquals(1, client.getCalls); + } finally { + SchemaDriver.destroy(); + } + } + + @Test + public void testGraphAndGraphSpaceRemovalInvalidateSchemaCaches() { + CachingKvClient client = new CachingKvClient(); + SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); + this.instance.set(driver); + try { + PropertyKey first = driver.propertyKey("space", "graph", IdGenerator.of(1), null); + PropertyKey other = driver.propertyKey("space", "other", IdGenerator.of(1), null); + PropertyKey elsewhere = driver.propertyKey("elsewhere", "graph", IdGenerator.of(1), null); + + client.publish("HUGEGRAPH/hg/EVENT/GRAPH/REMOVE", "space-graph"); + Assert.assertNotSame(first, driver.propertyKey("space", "graph", IdGenerator.of(1), null)); + Assert.assertSame(other, driver.propertyKey("space", "other", IdGenerator.of(1), null)); + Assert.assertEquals(4, client.getCalls); + + client.publish("HUGEGRAPH/hg/EVENT/GRAPHSPACE/REMOVE", "space"); + Assert.assertNotSame(other, driver.propertyKey("space", "other", IdGenerator.of(1), null)); + Assert.assertSame(elsewhere, driver.propertyKey("elsewhere", "graph", IdGenerator.of(1), null)); + Assert.assertEquals(5, client.getCalls); + } finally { + SchemaDriver.destroy(); + } + } + + @Test + public void testMetadataKeysAndWatchSubscriptionsUseConfiguredCluster() { + CachingKvClient client = new CachingKvClient(); + SchemaDriver driver = new SchemaDriver(client, "alternate", 10, 60_000L); + this.instance.set(driver); + try { + Assert.assertEquals(4, client.listeners.size()); + for (String key : client.listeners.keySet()) { + Assert.assertTrue(key, key.startsWith("HUGEGRAPH/alternate/EVENT/")); + } + SchemaGraph graph = new SchemaGraph("DEFAULT", "hugegraph", PDConfig.of("127.0.0.1:8686"), + "alternate"); + Assert.assertEquals("HUGEGRAPH/alternate/GRAPHSPACE/DEFAULT/GRAPH_CONF/hugegraph", + client.lastGetKey); + graph.propertyKey(IdGenerator.of(1)); + Assert.assertEquals("HUGEGRAPH/alternate/GRAPHSPACE/DEFAULT/hugegraph/SCHEMA/PROPERTY_KEY/ID/1", + client.lastGetKey); + driver.propertyKeys("DEFAULT", "hugegraph", graph); + Assert.assertEquals("HUGEGRAPH/alternate/GRAPHSPACE/DEFAULT/hugegraph/SCHEMA/PROPERTY_KEY/NAME", + client.lastScanPrefix); + } finally { + SchemaDriver.destroy(); + } + } + + @Test + public void testStoreSupplierMapsRpcNamespaceToSchemaGraphAndConfiguredCluster() throws Exception { + CachingKvClient client = new CachingKvClient(); + this.instance.set(new SchemaDriver(client, "alternate", 10, 60_000L)); + HgStoreEngine engine = HgStoreEngine.getInstance(); + Field optionsField = HgStoreEngine.class.getDeclaredField("options"); + optionsField.setAccessible(true); + Object previousOptions = optionsField.get(engine); + boolean previousClosing = engine.isClosing().getAndSet(false); + Field cacheField = BusinessHandlerImpl.class.getDeclaredField("GRAPH_SUPPLIER_CACHE"); + cacheField.setAccessible(true); + @SuppressWarnings("unchecked") + Map cache = (Map) cacheField.get(null); + Map previousCache = new HashMap<>(cache); + HgStoreEngineOptions options = new HgStoreEngineOptions(); + options.setPdAddress("127.0.0.1:8686"); + options.setPdCluster("alternate"); + optionsField.set(engine, options); + cache.clear(); + try { + HugeGraphSupplier graph = BusinessHandlerImpl.getGraphSupplier("CODEC_TEST/row_graph/g"); + Assert.assertEquals("CODEC_TEST-row_graph", graph.name()); + Assert.assertEquals("HUGEGRAPH/alternate/GRAPHSPACE/CODEC_TEST/GRAPH_CONF/row_graph", + client.lastGetKey); + graph.propertyKey(IdGenerator.of(1)); + Assert.assertEquals("HUGEGRAPH/alternate/GRAPHSPACE/CODEC_TEST/row_graph/SCHEMA/PROPERTY_KEY/ID/1", + client.lastGetKey); + Assert.assertSame(graph, BusinessHandlerImpl.getGraphSupplier("CODEC_TEST/row_graph/g")); + for (String invalid : new String[]{"plain", "/row_graph/g", "CODEC_TEST//g"}) { + try { + BusinessHandlerImpl.getGraphSupplier(invalid); + Assert.fail("Invalid graph namespace must be rejected: " + invalid); + } catch (HgStoreException expected) { + Assert.assertTrue(expected.getMessage().contains("Graph must include")); + } + } + } finally { + BusinessHandlerImpl.closeSchemaResources(); + cache.putAll(previousCache); + optionsField.set(engine, previousOptions); + engine.isClosing().set(previousClosing); + } + } + + @Test + public void testSharedDriverRejectsConflictingClusterAndReusesMatchingCluster() { + CachingKvClient client = new CachingKvClient(); + SchemaDriver driver = new SchemaDriver(client, "alternate", 10, 60_000L); + this.instance.set(driver); + PDConfig config = PDConfig.of("127.0.0.1:8686"); + try { + Assert.assertSame(driver, SchemaDriver.getOrInit(config, "alternate")); + try { + SchemaDriver.getOrInit(config, "hg"); + Assert.fail("Conflicting metadata cluster must fail before reusing the driver"); + } catch (NotAllowException expected) { + Assert.assertTrue(expected.getMessage().contains("alternate")); + } + Assert.assertSame(driver, SchemaDriver.getInstance()); + } finally { + SchemaDriver.destroy(); + } + } + + @SuppressWarnings("unchecked") + private static AtomicReference instanceReference() throws Exception { + Field field = SchemaDriver.class.getDeclaredField("INSTANCE"); + field.setAccessible(true); + return (AtomicReference) field.get(null); + } + + private static class TrackingKvClient extends KvClient { + + protected volatile boolean closed; + + TrackingKvClient() { + super(PDConfig.of("127.0.0.1:8686")); + } + + @Override + public void listen(String key, Consumer consumer) throws PDException { + // Avoid opening a real PD stream while constructing SchemaDriver. + } + + @Override + public void close() { + this.closed = true; + super.close(); + } + } + + private static class CachingKvClient extends TrackingKvClient { + + private final Map> listeners = new HashMap<>(); + private int getCalls; + private String lastGetKey; + private String lastScanPrefix; + + @Override + public void listen(String key, Consumer consumer) { + this.listeners.put(key, consumer); + } + + @Override + public KResponse get(String key) { + this.getCalls++; + this.lastGetKey = key; + return KResponse.newBuilder().setValue("{\"id\":1,\"name\":\"name\"}").build(); + } + + @Override + public ScanPrefixResponse scanPrefix(String prefix) { + this.lastScanPrefix = prefix; + return ScanPrefixResponse.getDefaultInstance(); + } + + private void publish(String key, String graph) { + WatchEvent event = WatchEvent.newBuilder() + .setType(WatchType.Put) + .setCurrent(WatchKv.newBuilder().setValue(graph)) + .build(); + this.listeners.get(key).accept(WatchResponse.newBuilder().addEvents(event).build()); + } + } + + private static class BlockingCloseKvClient extends TrackingKvClient { + + private final CountDownLatch closeStarted = new CountDownLatch(1); + private final CountDownLatch allowClose = new CountDownLatch(1); + + @Override + public void close() { + this.closeStarted.countDown(); + try { + this.allowClose.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException("Client close was interrupted", e); + } + super.close(); + } + + private void awaitCloseStarted() throws InterruptedException { + Assert.assertTrue(this.closeStarted.await(5L, TimeUnit.SECONDS)); + } + } + + private static class FailingListenKvClient extends TrackingKvClient { + + private int listenCalls; + + @Override + public void listen(String key, Consumer consumer) throws PDException { + if (++this.listenCalls == 2) { + throw new PDException(-1, "listener startup failed"); + } + } + } +} diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt new file mode 100644 index 0000000000..abf389945d --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.serializer.BinarySerializer; +import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.backend.store.BackendEntry; +import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.type.define.WriteType; + +public class LegacyRowFixtureWriter { + private static final long NOW = 1609459200000L; + private static final long EXPIRY = NOW + 60000L; + private static final Map PROPERTIES = new HashMap<>(); + private static final Map VERTICES = new HashMap<>(); + private static final Map EDGES = new HashMap<>(); + private static final Map INDEXES = new HashMap<>(); + private static HugeGraph fixtureGraph; + private static FixtureSerializer fixtureSerializer; + private static final Map ROWS = new LinkedHashMap<>(); + + public static void main(String[] args) throws Exception { + HugeGraph graph = (HugeGraph) Proxy.newProxyInstance( + HugeGraph.class.getClassLoader(), new Class[]{HugeGraph.class}, + (proxy, method, values) -> { + switch (method.getName()) { + case "now": return NOW; + case "name": return "legacy-fixture"; + case "hugegraph": return proxy; + case "propertyKey": return PROPERTIES.get(((Id) values[0]).asLong()); + case "vertexLabel": + case "vertexLabelOrNone": return VERTICES.get(((Id) values[0]).asLong()); + case "edgeLabel": + case "edgeLabelOrNone": return EDGES.get(((Id) values[0]).asLong()); + case "indexLabel": return INDEXES.get(((Id) values[0]).asLong()); + default: throw new AssertionError("Unexpected graph call: " + method); + } + }); + fixtureGraph = graph; + PropertyKey single = property(graph, 1, "age", Cardinality.SINGLE); + PropertyKey list = property(graph, 2, "scores", Cardinality.LIST); + PropertyKey set = property(graph, 3, "groups", Cardinality.SET); + VertexLabel vertexLabel = new VertexLabel(graph, IdGenerator.of(4L), "person"); + vertexLabel.ttl(60000L); + vertexLabel.properties(single.id(), list.id(), set.id()); + VERTICES.put(4L, vertexLabel); + EdgeLabel edgeLabel = new EdgeLabel(graph, IdGenerator.of(5L), "knows"); + edgeLabel.ttl(60000L); + edgeLabel.frequency(Frequency.MULTIPLE); + edgeLabel.links(Pair.of(vertexLabel.id(), vertexLabel.id())); + edgeLabel.properties(single.id(), list.id(), set.id()); + EDGES.put(5L, edgeLabel); + HugeVertex source = new HugeVertex(graph, IdGenerator.of(1L), vertexLabel); + HugeVertex target = new HugeVertex(graph, IdGenerator.of(2L), vertexLabel); + fill(source, single, list, set); + source.expiredTime(EXPIRY); + FixtureSerializer serializer = new FixtureSerializer(); + fixtureSerializer = serializer; + System.out.println("Row writer loaded from " + BinarySerializer.class.getProtectionDomain() + .getCodeSource().getLocation()); + row("vertex", serializer.writeVertex(source)); + HugeEdge edge = new HugeEdge(graph, + new EdgeId(source.id(), Directions.OUT, edgeLabel.id(), edgeLabel.id(), + "2026!x", target.id()), edgeLabel); + edge.vertices(true, source, target); + fill(edge, single, list, set); + edge.expiredTime(EXPIRY); + row("edge.out", serializer.writeEdge(edge)); + row("edge.in", serializer.writeEdge(edge.switchOwner())); + PropertyKey olapKey = property(graph, 9, "rank", Cardinality.SINGLE); + olapKey.writeType(WriteType.OLAP_COMMON); + HugeVertex olap = new HugeVertex(graph, source.id(), VertexLabel.OLAP_VL); + olap.addProperty(olapKey, 42); + row("olap", serializer.writeVertex(olap)); + property(graph, 16L, "weight", Cardinality.SINGLE).dataType(DataType.LONG); + property(graph, 17L, "name", Cardinality.SINGLE).dataType(DataType.TEXT); + index("index.secondary", graph, serializer, 6L, IndexType.SECONDARY, "alice"); + index("index.int", graph, serializer, 7L, IndexType.RANGE_INT, 7); + index("index.long", graph, serializer, 8L, IndexType.RANGE_LONG, 7L); + VertexLabel timeless = new VertexLabel(graph, IdGenerator.of(10L), "timeless"); + timeless.properties(single.id(), list.id(), set.id()); + VERTICES.put(10L, timeless); + HugeVertex timelessVertex = new HugeVertex(graph, IdGenerator.of(3L), timeless); + fill(timelessVertex, single, list, set); + row("vertex.untimed", serializer.writeVertex(timelessVertex)); + EdgeLabel timelessEdgeLabel = new EdgeLabel(graph, IdGenerator.of(11L), "untimed"); + timelessEdgeLabel.links(Pair.of(vertexLabel.id(), vertexLabel.id())); + timelessEdgeLabel.properties(single.id(), list.id(), set.id()); + EDGES.put(11L, timelessEdgeLabel); + HugeEdge timelessEdge = new HugeEdge(graph, + new EdgeId(source.id(), Directions.OUT, timelessEdgeLabel.id(), timelessEdgeLabel.id(), + "", target.id()), timelessEdgeLabel); + timelessEdge.vertices(true, source, target); + fill(timelessEdge, single, list, set); + row("edge.untimed", serializer.writeEdge(timelessEdge)); + index("index.secondary.untimed", graph, serializer, 12L, + IndexType.SECONDARY, "alice", 10L); + index("index.int.untimed", graph, serializer, 13L, IndexType.RANGE_INT, 7, 10L); + index("index.long.untimed", graph, serializer, 14L, IndexType.RANGE_LONG, 7L, 10L); + index("index.hashed", graph, serializer, 15L, IndexType.SECONDARY, + "long-field-".repeat(20)); + HugeIndex systemIndex = new HugeIndex(graph, IndexLabel.label(HugeType.VERTEX)); + systemIndex.fieldValues(4L); + systemIndex.elementIds(source.id(), EXPIRY); + row("index.system", serializer.writeIndex(systemIndex)); + HugeIndex edgeSystemIndex = new HugeIndex(graph, IndexLabel.label(HugeType.EDGE)); + edgeSystemIndex.fieldValues(5L); + edgeSystemIndex.elementIds(edge.id(), EXPIRY); + row("index.system.edge", serializer.writeIndex(edgeSystemIndex)); + String producer = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = producer.substring(0, producer.indexOf("*/") + 2); + StringBuilder encoded = new StringBuilder(license.replace("/*", "#") + .replace("*/", "#").replace(" *", "#")).append('\n'); + encoded.append("now=").append(NOW).append('\n'); + encoded.append("expiry=").append(EXPIRY).append('\n'); + ROWS.forEach((key, value) -> encoded.append(key).append('=').append(value).append('\n')); + Files.createDirectories(Path.of(args[0])); + Files.writeString(Path.of(args[0]).resolve("core-rows.properties"), encoded, + StandardCharsets.UTF_8); + System.out.println("Generated 15 real legacy BinarySerializer rows"); + } + + private static PropertyKey property(HugeGraph graph, long id, String name, + Cardinality cardinality) { + PropertyKey key = new PropertyKey(graph, IdGenerator.of(id), name); + key.dataType(DataType.INT); + key.cardinality(cardinality); + PROPERTIES.put(id, key); + return key; + } + + private static void fill(HugeElement element, PropertyKey single, + PropertyKey list, PropertyKey set) { + element.addProperty(single, 7); + element.addProperty(list, Arrays.asList(7, -1, 7)); + element.addProperty(set, Arrays.asList(7, -1)); + } + + private static void index(String name, HugeGraph graph, BinarySerializer serializer, + long id, IndexType type, Object value) { + index(name, graph, serializer, id, type, value, 4L); + } + + private static void index(String name, HugeGraph graph, BinarySerializer serializer, + long id, IndexType type, Object value, long baseId) { + IndexLabel label = new IndexLabel(graph, IdGenerator.of(id), name); + label.indexType(type); + label.indexFields(IdGenerator.of(type == IndexType.RANGE_LONG ? 16L : + type == IndexType.SECONDARY ? 17L : 1L)); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(IdGenerator.of(baseId)); + INDEXES.put(id, label); + HugeIndex index = new HugeIndex(graph, label); + index.fieldValues(value); + index.elementIds(IdGenerator.of(1L), baseId == 4L ? EXPIRY : 0L); + row(name, serializer.writeIndex(index)); + } + + private static void row(String name, BackendEntry entry) { + if (entry.type().isVertex()) { + HugeVertex decoded = fixtureSerializer.readVertex(fixtureGraph, entry); + if (decoded.sizeOfProperties() != 3 || + !Integer.valueOf(7).equals(decoded.getPropertyValue(IdGenerator.of(1L)))) { + throw new AssertionError("Legacy vertex self-read failed: " + name); + } + } else if (entry.type().isEdge()) { + HugeEdge decoded = fixtureSerializer.readEdge(fixtureGraph, entry); + if (decoded.sizeOfProperties() != 3 || + !Integer.valueOf(7).equals(decoded.getPropertyValue(IdGenerator.of(1L)))) { + throw new AssertionError("Legacy edge self-read failed: " + name); + } + } else if (entry.type() == HugeType.OLAP) { + HugeVertex decoded = new HugeVertex(fixtureGraph, IdGenerator.of(1L), VERTICES.get(4L)); + fixtureSerializer.parseOlap(entry.columns().iterator().next().value, decoded); + if (!Integer.valueOf(42).equals(decoded.getPropertyValue(IdGenerator.of(9L)))) { + throw new AssertionError("Legacy OLAP self-read failed"); + } + } else if (entry.type().isIndex()) { + ConditionQuery query = new ConditionQuery(entry.type()); + if (name.equals("index.secondary") || name.equals("index.secondary.untimed")) { + query.eq(HugeKeys.FIELD_VALUES, "alice"); + } else if (name.equals("index.hashed")) { + query.eq(HugeKeys.FIELD_VALUES, "long-field-".repeat(20)); + } else if (name.equals("index.system")) { + query.eq(HugeKeys.FIELD_VALUES, 4L); + } else if (name.equals("index.system.edge")) { + query.eq(HugeKeys.FIELD_VALUES, 5L); + } + HugeIndex decoded = fixtureSerializer.readIndex(fixtureGraph, query, entry); + Id expectedElement = name.equals("index.system.edge") ? + new EdgeId(IdGenerator.of(1L), Directions.OUT, + IdGenerator.of(5L), IdGenerator.of(5L), + "2026!x", IdGenerator.of(2L)) : IdGenerator.of(1L); + if (!decoded.elementIds().contains(expectedElement)) { + throw new AssertionError("Legacy index self-read failed: " + name); + } + } + ROWS.put(name + ".type", entry.type().name()); + ROWS.put(name + ".id", hex(entry.id().asBytes())); + ROWS.put(name + ".ttl", String.valueOf(entry.ttl())); + ROWS.put(name + ".columns", String.valueOf(entry.columnsSize())); + int number = 0; + for (BackendColumn column : entry.columns()) { + ROWS.put(name + ".column." + number + ".name", hex(column.name)); + ROWS.put(name + ".column." + number + ".value", hex(column.value)); + number++; + } + } + + private static class FixtureSerializer extends BinarySerializer { + private void parseOlap(byte[] bytes, HugeVertex vertex) { + super.parseVertexOlap(bytes, vertex); + } + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { + text.append(String.format("%02x", value & 0xff)); + } + return text.toString(); + } +} diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt new file mode 100644 index 0000000000..e51eca9f31 --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Collections; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.backend.query.IdPrefixQuery; +import org.apache.hugegraph.backend.serializer.BinarySerializer; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.HugeKeys; + +public class LegacyServerIndexQueryProbe { + public static void main(String[] args) throws Exception { + String input = "long-field-".repeat(20); + String value = ConditionQuery.concatValues(Collections.singletonList(input)); + ConditionQuery query = new ConditionQuery(HugeType.SECONDARY_INDEX); + query.eq(HugeKeys.INDEX_LABEL_ID, IdGenerator.of(15L)); + query.eq(HugeKeys.FIELD_VALUES, value); + IdPrefixQuery encoded = (IdPrefixQuery) new BinarySerializer().writeQuery(query); + String text = "server.query.field.length=" + value.length() + "\n" + + "server.query.prefix=" + hex(encoded.prefix().asBytes()) + "\n"; + Files.writeString(Path.of(args[0]).resolve("index-builder-contract.properties"), text, + StandardCharsets.UTF_8, StandardOpenOption.APPEND); + System.out.println("Original Server query: field " + value.length() + + " -> prefix " + hex(encoded.prefix().asBytes())); + } + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { text.append(String.format("%02x", value & 0xff)); } + return text.toString(); + } +} diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt new file mode 100644 index 0000000000..c4a3fbdc2c --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.builder.IndexBuilder; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IndexType; + +public class LegacyStoreIndexBuilderProbe { + public static void main(String[] args) throws Exception { + HugeConfig config = new HugeConfig(Collections.emptyMap()); + PropertyKey pkey = new PropertyKey(null, IdGenerator.of(17L), "name"); + pkey.dataType(DataType.TEXT); + VertexLabel vlabel = new VertexLabel(null, IdGenerator.of(4L), "person"); + vlabel.properties(pkey.id()); + vlabel.ttl(60000L); + HugeGraphSupplier graph = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, values) -> { + switch (method.getName()) { + case "configuration": return config; + case "propertyKey": return pkey; + case "vertexLabel": + case "vertexLabelOrNone": return vlabel; + case "now": return 1609459200000L; + case "name": return "legacy-fixture"; + default: throw new AssertionError("Unexpected supplier call: " + method); + } + }); + IndexLabel ilabel = new IndexLabel(graph, IdGenerator.of(15L), "by-name"); + ilabel.indexType(IndexType.SECONDARY); + ilabel.baseType(HugeType.VERTEX_LABEL); + ilabel.baseValue(vlabel.id()); + ilabel.indexFields(pkey.id()); + String value = "long-field-".repeat(20); + BaseVertex vertex = new BaseVertex(IdGenerator.of(1L), vlabel); + vertex.addProperty(pkey, value); + vertex.expiredTime(1609459260000L); + IndexBuilder builder = new IndexBuilder(graph); + Index index = builder.buildIndex(vertex, ilabel).get(0); + BackendColumn column = new BinaryElementSerializer().writeIndex(index); + String producer = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = producer.substring(0, producer.indexOf("*/") + 2); + String text = license.replace("/*", "#").replace("*/", "#").replace(" *", "#") + "\n" + + "input.length=" + value.length() + "\n" + + "store.builder.field.length=" + index.fieldValues().toString().length() + "\n" + + "store.builder.field=" + index.fieldValues() + "\n" + + "store.builder.key=" + hex(column.name) + "\n" + + "store.builder.value=" + hex(column.value) + "\n"; + Files.writeString(Path.of(args[0]).resolve("index-builder-contract.properties"), text, + StandardCharsets.UTF_8); + System.out.println("Original Store IndexBuilder: input " + value.length() + + " -> field " + index.fieldValues()); + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { text.append(String.format("%02x", value & 0xff)); } + return text.toString(); + } +} diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt new file mode 100644 index 0000000000..9a9a468c4d --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IndexType; + +public class LegacyStoreIndexFixtureWriter { + private static final long EXPIRY = 1609459260000L; + private static final Map INDEXES = new HashMap<>(); + private static final Map PROPERTIES = new HashMap<>(); + private static final Map OUTPUT = new LinkedHashMap<>(); + + public static void main(String[] args) throws Exception { + VertexLabel label = new VertexLabel(null, IdGenerator.of(4L), "person"); + label.ttl(60000L); + HugeGraphSupplier graph = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, values) -> { + switch (method.getName()) { + case "vertexLabel": + case "vertexLabelOrNone": return label; + case "indexLabel": return INDEXES.get(((Id) values[0]).asLong()); + case "propertyKey": return PROPERTIES.get(((Id) values[0]).asLong()); + case "now": return 1609459200000L; + case "name": return "legacy-fixture"; + default: throw new AssertionError("Unexpected supplier call: " + method); + } + }); + PropertyKey intKey = new PropertyKey(graph, IdGenerator.of(1L), "age"); + intKey.dataType(DataType.INT); + PROPERTIES.put(1L, intKey); + PropertyKey longKey = new PropertyKey(graph, IdGenerator.of(16L), "weight"); + longKey.dataType(DataType.LONG); + PROPERTIES.put(16L, longKey); + BinaryElementSerializer serializer = new BinaryElementSerializer(); + System.out.println("Store index writer loaded from " + BinaryElementSerializer.class + .getProtectionDomain().getCodeSource().getLocation()); + user("secondary", graph, serializer, 6L, IndexType.SECONDARY, "alice"); + user("int", graph, serializer, 7L, IndexType.RANGE_INT, 7); + user("long", graph, serializer, 8L, IndexType.RANGE_LONG, 7L); + Index system = new Index(graph, IndexLabel.label(HugeType.VERTEX), true); + system.fieldValues(4L); + system.elementIds(IdGenerator.of(1L), EXPIRY); + row("system", serializer, graph, system); + Index edgeSystem = new Index(graph, IndexLabel.label(HugeType.EDGE), true); + edgeSystem.fieldValues(5L); + edgeSystem.elementIds(new EdgeId(IdGenerator.of(1L), Directions.OUT, + IdGenerator.of(5L), IdGenerator.of(5L), "2026!x", IdGenerator.of(2L)), EXPIRY); + row("system.edge", serializer, graph, edgeSystem); + String source = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = source.substring(0, source.indexOf("*/") + 2); + StringBuilder text = new StringBuilder(license.replace("/*", "#") + .replace("*/", "#").replace(" *", "#")).append('\n'); + OUTPUT.forEach((key, value) -> text.append(key).append('=').append(value).append('\n')); + Files.writeString(Path.of(args[0]).resolve("store-index-rows.properties"), text, + StandardCharsets.UTF_8); + System.out.println("Generated 5 original Store TTL index rows"); + } + + private static void user(String name, HugeGraphSupplier graph, + BinaryElementSerializer serializer, long id, + IndexType type, Object value) { + IndexLabel label = new IndexLabel(graph, IdGenerator.of(id), "index-" + id); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(IdGenerator.of(4L)); + label.indexType(type); + label.indexFields(IdGenerator.of(type == IndexType.RANGE_LONG ? 16L : 1L)); + INDEXES.put(id, label); + Index index = new Index(graph, label, true); + index.fieldValues(value); + index.elementIds(IdGenerator.of(1L), EXPIRY); + row(name, serializer, graph, index); + } + + private static void row(String name, BinaryElementSerializer serializer, + HugeGraphSupplier graph, Index index) { + BackendColumn column = serializer.writeIndex(index); + Index decoded = serializer.parseIndex(graph, column, null); + if (decoded.expiredTime() != EXPIRY) { + throw new AssertionError("Legacy Store reader TTL mismatch: " + name); + } + OUTPUT.put(name + ".name", hex(column.name)); + OUTPUT.put(name + ".value", hex(column.value)); + OUTPUT.put(name + ".expiry", String.valueOf(EXPIRY)); + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { + text.append(String.format("%02x", value & 0xff)); + } + return text.toString(); + } +} diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/README.md b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/README.md new file mode 100644 index 0000000000..1fc06cbd2a --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/README.md @@ -0,0 +1,147 @@ + + +# Legacy core rows for Store ingress tests + +Source baseline: `hugegraph/hugegraph` commit +`2f827d6e8c9c62ae858f2fc122b3a192d015e2f4`, frozen core jar SHA-256 +`e53a15206fcf2f9b6ee4ba30146a1fb9814d3bf9275bdfe3f861796706fb7ce4`. +Producer uses Java 11, UTF-8 and UTC. + +## Complete BinarySerializer row fixtures + +`core-rows.properties` stores 15 complete rows emitted by the original +`BinarySerializer` from the same frozen core jar. Names, values and row IDs +are hex; `type`, `ttl` and `columns` record the real BackendEntry metadata. +These are not manually assembled from scalar fixtures. + +`LegacyRowFixtureWriter.java.txt` records the exact producer and schema. +A dynamic proxy supplies only schema lookup and a fixed clock; it throws on +unexpected graph calls. The real baseline HugeVertex/HugeEdge/HugeIndex, +BinarySerializer, and property implementations build each row. The producer +also validates every row using the original baseline reader. For OLAP it +exposes the protected original `parseVertexOlap` via a reader-only subclass; +it does not override any encoding methods. + +Schema and expected values: + +| Schema | Definition | +|---|---| +| Property 1 | `age`, INT SINGLE, value 7 | +| Property 2 | `scores`, INT LIST, value `[7, -1, 7]` | +| Property 3 | `groups`, INT SET, values `{-1, 7}` | +| Property 9 | `rank`, INT SINGLE OLAP_COMMON, value 42 | +| Property 16 | `weight`, LONG SINGLE, range-long index field | +| Property 17 | `name`, TEXT SINGLE, secondary index field | +| Vertex label 4 | `person`, TTL 60000, properties 1/2/3 | +| Vertex label 10 | `timeless`, no TTL, properties 1/2/3 | +| Edge label 5 | `knows`, TTL 60000, link 4→4, properties 1/2/3 | +| Edge label 11 | `untimed`, no TTL, link 4→4, properties 1/2/3 | +| Index labels 6/7/8 | secondary/range-int/range-long, base label 4 | +| Index labels 12/13/14 | secondary/range-int/range-long, base label 10 | +| Index label 15 | secondary, base label 4, hashed long string key | + +Timed rows expire at `1609459260000`, with the producer clock fixed at +`1609459200000`. The vertex ID is 1 (untimed vertex 3). Outgoing/incoming +edges connect 1 and 2, with sort value `2026!x` (untimed edge has an empty +sort value). Index field values are `alice`, integer 7, long 7, or +`"long-field-".repeat(20)` for the hashed row. `index.system` uses the +original system vertex-label index with field value 4 and no persisted TTL. +`index.system.edge` similarly uses field value 5 and the full edge ID. Both +original Core writers receive a positive expiry yet persist no expiry suffix +or value. The old Store writer persists the same key plus the 13-byte value +envelope for both label index kinds. + +The writer uses default BinarySerializer flags: key and index ID prefixes +enabled, partition prefix disabled. The OLAP column name is the single +vertex ID, and its value is the property ID followed by the untagged scalar. +The shared merged-row test supplies the existing vertex, matching the legacy +reader's first main row plus subsequent OLAP columns convention. + +Compile the row producer against the isolated baseline core runtime classpath +and invoke `LegacyRowFixtureWriter `. +Use Java 11, UTF-8 and UTC as above. The captured full-row file SHA-256 is +`d90cfe0b349edb832bf7425b6b8e2ddb06b3eff3f29e834cf8363b0d2fb84662`. +The exact same licensed fixture and producer are provided to Store's test +resources so ingress tests consume the original bytes directly. + +These complete row checks cover schema-driven property-group framing, TTL, +OLAP merging, ordinary/range/hashed/system indexes and their direct TTL +readers. They still do not prove every partition layout, storage transaction, +or RocksDB/HStore runtime path. + +`property.OBJECT_UNSUPPORTED_COLLECTION` retains those original bytes only +for the skip-path test. Skipping must preserve the trailing marker and TTL +without invoking Kryo instantiation. It is not used as a readable property +compatibility assertion. + + +## Original Store index TTL rows + +`store-index-rows.properties` comes from the frozen baseline struct jar's +original `BinaryElementSerializer.writeIndex`, using +`LegacyStoreIndexFixtureWriter.java.txt`. The producer also decodes each row +with that same original implementation and verifies expiration time. +It emits secondary/range-int/range-long user indexes and the system +vertex-label and edge-label indexes, each with expiration `1609459260000`. +The index schemas and IDs match the complete core-row fixtures above. + +This original Store format places no expiration suffix in the key. Its +value is the exact 13-byte envelope `0x00 + Base64(big-endian long)`. +The shared schema reader must continue reading these old rows while the +new schema writer retains the pinned Server key/hash/TTL layout. The +still-supported tagged writer is separately checked against the original +Store bytes. The original system index persists TTL in this value envelope; +the original core system-index fixture does not persist TTL. + +Compile and run this producer with the frozen struct jar first, no core jar, +and the module's runtime dependencies; invoke +`LegacyStoreIndexFixtureWriter `. +The captured fixture SHA-256 is +`e9e9c967884d0d91b6cf6d5eabf2050a9bad0fe7898d1c47b58535ebdf1b9431`. + + +## Existing IndexBuilder/query mismatch + + +`index-builder-contract.properties` records two actual pinned execution +paths. Run `LegacyStoreIndexBuilderProbe` against the original struct jar +first; then run `LegacyServerIndexQueryProbe` against the original core jar +in a separate process. The second appends the Server prefix to the same +licensed resource. The Store probe requires the pinned IndexBuilder's +analyzer dependencies even though this example builds a secondary index. + +For TEXT property 17, index label 15, base vertex label 4, and +`"long-field-".repeat(20)`, Store's real `buildIndex` truncates the 220-character +value to `long-field-long-fiel` (20 characters). Its emitted key starts with +that shortened literal. Server's real `BinarySerializer.writeQuery`, using +`ConditionQuery.concatValues` over the full value, emits the hashed prefix +`53493a463a323234303534613200`. The old Store key does not match it. +This is an existing builder/query contract defect, not a fixture assembled +from separate guessed helper outputs. New writer/query alignment tests use +the captured original Server prefix, while retaining old Store row decoding. + +The fixture SHA-256 is +`3be36ba02c4afd58aab383549b041368fab4b9e8e32474122457b5608970161b`. + +The label TTL regression tests exercise actual Core `readIndex`, recovered +expiration, `expiredElementIds`, clone/reset and deletion encoding, then Core +append and re-read. Both deletion and append retain the exact original Store +key; Core's primitive encoder still emits the original empty value. The +shared storage writer retains the old envelope on that same key, keeping +label expiry available without introducing an expiry suffix or duplicate +candidate key. diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties new file mode 100644 index 0000000000..fd489e58c1 --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties @@ -0,0 +1,108 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +now=1609459200000 +expiry=1609459260000 +vertex.type=VERTEX +vertex.id=0801 +vertex.ttl=60000 +vertex.columns=1 +vertex.column.0.name=0801 +vertex.column.0.value=08040301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +edge.out.type=EDGE_OUT +edge.out.id=08018208050805323032362178000802 +edge.out.ttl=60000 +edge.out.columns=1 +edge.out.column.0.name=08018208050805323032362178000802 +edge.out.column.0.value=0301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +edge.in.type=EDGE_IN +edge.in.id=08028c08050805323032362178000801 +edge.in.ttl=60000 +edge.in.columns=1 +edge.in.column.0.name=08028c08050805323032362178000801 +edge.in.column.0.value=0301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +olap.type=OLAP +olap.id=0801 +olap.ttl=0 +olap.columns=1 +olap.column.0.name=0801 +olap.column.0.value=092a +index.secondary.type=SECONDARY_INDEX +index.secondary.id=53493a363a616c69636500 +index.secondary.ttl=60000 +index.secondary.columns=1 +index.secondary.column.0.name=53493a363a616c696365000801aeebd9fdb460 +index.secondary.column.0.value= +index.int.type=RANGE_INT_INDEX +index.int.id=a00000000780000007 +index.int.ttl=60000 +index.int.columns=1 +index.int.column.0.name=a000000007800000070801aeebd9fdb460 +index.int.column.0.value= +index.long.type=RANGE_LONG_INDEX +index.long.id=a2000000088000000000000007 +index.long.ttl=60000 +index.long.columns=1 +index.long.column.0.name=a20000000880000000000000070801aeebd9fdb460 +index.long.column.0.value= +vertex.untimed.type=VERTEX +vertex.untimed.id=0803 +vertex.untimed.ttl=0 +vertex.untimed.columns=1 +vertex.untimed.column.0.name=0803 +vertex.untimed.column.0.value=080a0301070203078fffffff7f0703028fffffff7f07 +edge.untimed.type=EDGE_OUT +edge.untimed.id=080182080b080b000802 +edge.untimed.ttl=0 +edge.untimed.columns=1 +edge.untimed.column.0.name=080182080b080b000802 +edge.untimed.column.0.value=0301070203078fffffff7f0703028fffffff7f07 +index.secondary.untimed.type=SECONDARY_INDEX +index.secondary.untimed.id=53493a433a616c69636500 +index.secondary.untimed.ttl=0 +index.secondary.untimed.columns=1 +index.secondary.untimed.column.0.name=53493a433a616c696365000801 +index.secondary.untimed.column.0.value= +index.int.untimed.type=RANGE_INT_INDEX +index.int.untimed.id=a00000000d80000007 +index.int.untimed.ttl=0 +index.int.untimed.columns=1 +index.int.untimed.column.0.name=a00000000d800000070801 +index.int.untimed.column.0.value= +index.long.untimed.type=RANGE_LONG_INDEX +index.long.untimed.id=a20000000e8000000000000007 +index.long.untimed.ttl=0 +index.long.untimed.columns=1 +index.long.untimed.column.0.name=a20000000e80000000000000070801 +index.long.untimed.column.0.value= +index.hashed.type=SECONDARY_INDEX +index.hashed.id=53493a463a323234303534613200 +index.hashed.ttl=60000 +index.hashed.columns=1 +index.hashed.column.0.name=53493a463a3232343035346132000801aeebd9fdb460 +index.hashed.column.0.value=6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d +index.system.type=VERTEX_LABEL_INDEX +index.system.id=56493a2d313a3400 +index.system.ttl=0 +index.system.columns=1 +index.system.column.0.name=56493a2d313a34000801 +index.system.column.0.value= +index.system.edge.type=EDGE_LABEL_INDEX +index.system.edge.id=45493a2d323a3500 +index.system.edge.ttl=0 +index.system.edge.columns=1 +index.system.edge.column.0.name=45493a2d323a35007e08018208050805323032362178000802 +index.system.edge.column.0.value= diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/index-builder-contract.properties b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/index-builder-contract.properties new file mode 100644 index 0000000000..a6139eef41 --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/index-builder-contract.properties @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +input.length=220 +store.builder.field.length=20 +store.builder.field=long-field-long-fiel +store.builder.key=53493a463a6c6f6e672d6669656c642d6c6f6e672d6669656c000801 +store.builder.value=00414141426472732f576d413d +server.query.field.length=220 +server.query.prefix=53493a463a323234303534613200 diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties new file mode 100644 index 0000000000..7f5a599ed4 --- /dev/null +++ b/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +secondary.name=53493a363a616c696365000801 +secondary.value=00414141426472732f576d413d +secondary.expiry=1609459260000 +int.name=a000000007800000070801 +int.value=00414141426472732f576d413d +int.expiry=1609459260000 +long.name=a20000000880000000000000070801 +long.value=00414141426472732f576d413d +long.expiry=1609459260000 +system.name=56493a2d313a34000801 +system.value=00414141426472732f576d413d +system.expiry=1609459260000 +system.edge.name=45493a2d323a35007e08018208050805323032362178000802 +system.edge.value=00414141426472732f576d413d +system.edge.expiry=1609459260000 diff --git a/hugegraph-struct/README.md b/hugegraph-struct/README.md index f004bc0c23..df010c1696 100644 --- a/hugegraph-struct/README.md +++ b/hugegraph-struct/README.md @@ -1,209 +1,78 @@ # HugeGraph-Struct -### Overview - -**hugegraph-struct** is a foundational data structures module that defines the core abstractions and type definitions shared across HugeGraph's distributed components. It serves as the "data contract layer" enabling type-safe communication between hugegraph-pd (Placement Driver), hugegraph-store (distributed storage), and hugegraph-server (graph engine). - -**Key Characteristics**: -- Pure data structure definitions without business logic -- Lightweight and stateless (no `HugeGraph` instance dependencies) -- Shared type system for distributed RPC communication -- Binary serialization for efficient storage and network transmission - -### Why hugegraph-struct? - -#### The Problem - -Originally, all data structures and graph engine logic resided in `hugegraph-server/hugegraph-core`. As HugeGraph evolved toward a distributed architecture, this created several challenges: - -1. **Tight Coupling**: PD and Store components needed schema definitions but not the entire graph engine -2. **Circular Dependencies**: Distributed components couldn't share types without pulling in heavy dependencies -3. **Build Inefficiency**: Changes to core required rebuilding all dependent modules -4. **Large Dependencies**: PD/Store had to depend on Jersey, JRaft, K8s client, and other server-specific libraries - -#### The Solution - -We extracted **stateless data structures** from `hugegraph-core` into a separate `hugegraph-struct` module: - -``` -Before (Monolithic): -hugegraph-server/hugegraph-core (everything together) - ├─ Data structures (schema, types, IDs) - ├─ Graph engine (traversal, optimization) - ├─ Transactions (GraphTransaction, SchemaTransaction) - ├─ Storage backends (memory, raft, cache) - └─ Business logic (jobs, tasks, auth) - -After (Modular): -hugegraph-struct (shared foundation) - ├─ Schema definitions (VertexLabel, EdgeLabel, PropertyKey, IndexLabel) - ├─ Type system (HugeType, DataType, IdStrategy) - ├─ Data structures (BaseVertex, BaseEdge, BaseProperty) - ├─ Serialization (BytesBuffer, BinarySerializer) - ├─ Query abstractions (Query, ConditionQuery, Aggregate) - └─ Utilities (ID generation, text analyzers, exceptions) - -hugegraph-core (graph engine only) - ├─ Depends on hugegraph-struct - ├─ Implements graph engine logic - ├─ Manages transactions and storage - └─ Provides TinkerPop API -``` - -### Module Responsibilities - -| Module | Purpose | Dependencies | -|--------|---------|--------------| -| **hugegraph-struct** | Shared data structures, type definitions, serialization | Minimal (Guava, TinkerPop, serialization libs) | -| **hugegraph-core** | Graph engine, traversal, transactions, storage abstraction | hugegraph-struct + heavy libs (Jersey, JRaft, K8s) | -| **hugegraph-pd** | Metadata coordination, service discovery | hugegraph-struct only | -| **hugegraph-store** | Distributed storage with Raft | hugegraph-struct only | - -### Dependency Architecture - -``` - hugegraph-struct (foundational) - ↑ - ┌──────────────────┼──────────────────┐ - │ │ │ - hugegraph-pd hugegraph-store hugegraph-core - │ │ │ - └──────────────────┼──────────────────┘ - ↓ - hugegraph-server (REST API) -``` - -**Build Order**: -```bash -# 1. Build struct first (required dependency) -mvn install -pl hugegraph-struct -am -DskipTests - -# 2. Then build dependent modules -mvn install -pl hugegraph-pd -am -DskipTests -mvn install -pl hugegraph-store -am -DskipTests -mvn install -pl hugegraph-server -am -DskipTests -``` - -### Migration Plan - -**Current Status (Transition Period)**: - -Both `hugegraph-struct` and `hugegraph-core` contain similar data structures for backward compatibility. This is a **temporary state** during the migration period. - -**Future Direction**: - -- ✅ **hugegraph-struct**: Will become the **single source of truth** for all data structure definitions -- ⚠️ **hugegraph-core**: Data structure definitions will be **gradually removed** and replaced with references to hugegraph-struct -- 🎯 **End Goal**: hugegraph-core will only contain graph engine logic and depend on hugegraph-struct for all type definitions - -**Migration Strategy**: - -1. **Phase 1 (Current)**: Both modules coexist; new features use struct -2. **Phase 2 (In Progress)**: Gradually migrate core's data structures to import from struct -3. **Phase 3 (Future)**: Remove duplicate definitions from core completely - -**Example Migration**: - -```java -// OLD (hugegraph-core) -import org.apache.hugegraph.schema.SchemaElement; // ❌ Will be deprecated - -// NEW (hugegraph-struct) -import org.apache.hugegraph.struct.schema.SchemaElement; // ✅ Use this -``` - -### Developer Guide - -#### When to Use hugegraph-struct - -Use struct when: -- Building distributed components (PD, Store) -- Defining data transfer objects (DTOs) for RPC -- Implementing serialization/deserialization logic -- Working with type definitions, schema elements, or IDs -- Creating shared utilities needed across modules - -#### When to Use hugegraph-core - -Use core when: -- Implementing graph engine features -- Working with TinkerPop API (Gremlin traversal) -- Managing transactions or backend storage -- Implementing graph algorithms or jobs -- Building server-side business logic - -#### Adding New Data Structures - -**Rule**: All new shared data structures should go into `hugegraph-struct`, not `hugegraph-core`. - -Example: -```java -// ✅ Correct: Add to hugegraph-struct/src/main/java/org/apache/hugegraph/struct/ -public class NewSchemaType extends SchemaElement { - // Pure data structure, no HugeGraph dependency -} - -// ❌ Wrong: Don't add to hugegraph-core unless it's graph engine logic -``` - -#### Modifying Existing Structures - -If you need to modify a data structure: - -1. **Check if it exists in struct**: Modify the struct version -2. **If it only exists in core**: Consider migrating it to struct first -3. **Update serialization**: Ensure binary compatibility or provide migration - -### Package Structure - -``` -org.apache.hugegraph/ -├── struct/schema/ # Schema definitions (VertexLabel, EdgeLabel, etc.) -├── structure/ # Graph elements (BaseVertex, BaseEdge, BaseProperty) -├── type/ # Type system (HugeType, DataType, IdStrategy) -├── id/ # ID generation and management -├── serializer/ # Binary serialization (BytesBuffer, BinarySerializer) -├── query/ # Query abstractions (Query, ConditionQuery, Aggregate) -├── analyzer/ # Text analyzers (8 Chinese NLP implementations) -├── auth/ # Auth utilities (JWT, constants) -├── backend/ # Backend abstractions (BinaryId, BackendColumn, Shard) -├── options/ # Configuration options -├── util/ # Utilities (encoding, compression, collections) -└── exception/ # Exception hierarchy -``` - -### Key Design Principles - -1. **Stateless**: No `HugeGraph` instance dependencies in struct -2. **Minimal Dependencies**: Only essential libraries (no Jersey, JRaft, K8s) -3. **Serialization-Friendly**: All structures support binary serialization -4. **Type Safety**: Strong typing for distributed RPC communication -5. **Backward Compatible**: Careful versioning to avoid breaking changes - -### Building and Testing +`hugegraph-struct` owns the shared foundations used by Server and Store: IDs, +schema metadata, base graph elements, query conditions, type codes and binary +encoding. Core builds the graph engine on these implementations instead of +maintaining a second copy. + +## Responsibilities + +| Owner | Responsibility | +|-------|----------------| +| `hugegraph-struct` | Shared models, queries, codecs, index building and analyzers | +| `hugegraph-common` | General utilities, shared JWT verification/signing and RPC configuration interfaces | +| `hugegraph-core` | Graph/TinkerPop adapters, transactions, traversal, backend execution and jobs | +| `hg-store-core` | Store execution and schema metadata access through PD | +| PD service | Placement/metadata service and its own authentication/transport adaptation | + +Struct is not a DTO-only module or dependency-free library. It retains the +libraries required by shared codecs, collections and analyzers, including +TinkerPop interfaces and shaded Kryo compatibility. It must not depend on core +or own PD connections, listeners and caches. + +`HugeGraphSupplier` lets shared operations obtain schema without a concrete +`HugeGraph`. It currently also supplies naming, configuration and time; +[further narrowing](https://github.com/hugegraph/hugegraph/issues/258) is tracked +separately. Store's `SchemaGraph` and `SchemaDriver` live in Store. The caller +owns their PD lifecycle. + +Core's `HugeVertex`/`HugeEdge` wrap shared `BaseVertex`/`BaseEdge` state and add +engine behavior. `BaseVertex` owns adjacency; core only caches wrapper identities. +Shared `Index` replaces `HugeIndex`, including index IDs and values. Index/OLAP +selection uses caller-supplied candidates and sinks; core still executes +transactions and backend updates. Engine serializers retain backend adaptation +and delegate shared encoding. These adapters have different responsibilities +from the shared implementation; a second algorithm or state collection is not +an adapter. + +## Packages and migration + +| Package under `org.apache.hugegraph` | Content | +|------------------------------------|---------| +| `struct.schema` | Schema metadata | +| `structure` | Base elements, indexes and shared index builder | +| `id`, `query`, `serializer` | IDs, query conditions and encoding | +| `type`, `backend` | Type codes and shared backend values | +| `analyzer`, `util`, `exception` | Shared analysis, codec helpers and exceptions | + +The 1.8.0 Java API migration removes the old core copies. For example, schema +metadata moves from `org.apache.hugegraph.schema` to +`org.apache.hugegraph.struct.schema`; engine schema mutation builders remain +in core. Applications using internal Java APIs must update imports and compile +against a consistent set of artifacts. + +See the [shared-foundation migration guide](../docs/shared-foundation-migration.md) +for ownership, upgrade requirements and compatibility checks. Existing client +REST DTOs need not be replaced merely because their names resemble these types. + +## Development and validation + +Run from the repository root: ```bash -# Build struct module -mvn clean install -DskipTests - -# Build with tests (when tests are added) -mvn clean install - -# From parent directory -cd /path/to/hugegraph mvn install -pl hugegraph-struct -am -DskipTests +mvn test -pl hugegraph-struct -am ``` -### Contributing - -When contributing to hugegraph-struct: +The first command builds without tests. Tests exist under `src/test/java`; +a successful build alone does not prove compatibility or distributed startup. +See [BUILDING](../docs/BUILDING.md) and module CI for service prerequisites. -1. **No Business Logic**: Keep it pure data structures -2. **No Graph Instances**: Avoid `HugeGraph graph` fields -3. **Document Changes**: Update AGENTS.md if adding new packages -4. **Binary Compatibility**: Consider serialization impact -5. **Minimal Dependencies**: Justify any new dependency additions +Change shared behavior once, in its canonical owner, and migrate consumers. +Changes to type codes, ID encoding, binary layout, query JSON or classification +must be checked against historical fixtures and Server/Store readers. Do not +restore deleted copies to resolve an import or dependency problem. -### License +## License -Apache License 2.0 - See [LICENSE](../LICENSE) file for details. +Apache License 2.0; see [LICENSE](../LICENSE). diff --git a/hugegraph-struct/pom.xml b/hugegraph-struct/pom.xml index a65c294681..101814b143 100644 --- a/hugegraph-struct/pom.xml +++ b/hugegraph-struct/pom.xml @@ -36,18 +36,6 @@ - - org.apache.hugegraph - hg-pd-client - ${project.version} - - - - jakarta.ws.rs - jakarta.ws.rs-api - 3.0.0 - - org.apache.tinkerpop gremlin-core @@ -60,6 +48,18 @@ ${tinkerpop.version} test + + com.carrotsearch + hppc + 0.7.1 + + + + junit + junit + 4.13.2 + test + com.google.code.gson @@ -83,11 +83,6 @@ guava ${guava.version} - - - - - org.apache.tinkerpop gremlin-shaded @@ -149,34 +144,17 @@ com.hankcs hanlp - portable-1.5.0 + portable-1.8.3 org.apache.lucene lucene-analyzers-smartcn - 7.4.0 + 8.11.2 org.apache.lucene lucene-core - 7.4.0 - - - io.jsonwebtoken - jjwt-api - 0.11.2 - - - io.jsonwebtoken - jjwt-impl - 0.11.2 - runtime - - - io.jsonwebtoken - jjwt-jackson - 0.11.2 - runtime + 8.11.2 com.huaban @@ -186,7 +164,7 @@ org.lionsoul jcseg-core - 2.2.0 + 2.6.2 com.chenlb.mmseg4j @@ -197,8 +175,47 @@ com.janeluo ikanalyzer 2012_u6 + + + org.apache.lucene + lucene-core + + + org.apache.lucene + lucene-analyzers-common + + + + + + org.codehaus.mojo + flatten-maven-plugin + 1.2.7 + + true + resolveCiFriendliesOnly + + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + + + diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/HugeGraphSupplier.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/HugeGraphSupplier.java index 2ac547db8a..5298800a5d 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/HugeGraphSupplier.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/HugeGraphSupplier.java @@ -19,9 +19,14 @@ package org.apache.hugegraph; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import java.util.Collection; import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.struct.schema.EdgeLabel; @@ -34,6 +39,7 @@ * Actually, it would be better if this interface be called * "HugeGraphSchemaSupplier". */ +// TODO(hugegraph/hugegraph#258): separate schema access from configuration and clock capabilities. public interface HugeGraphSupplier { List mapPkId2Name(Collection ids); @@ -70,9 +76,33 @@ default EdgeLabel edgeLabelOrNone(Id id) { String name(); + default String spaceGraphName() { + return this.name(); + } + HugeConfig configuration(); default long now() { return DateUtil.now().getTime(); } + + + default List mapElId2Name(Collection ids) { + List names = new ArrayList<>(ids.size()); + for (Id id : ids) { + SchemaElement schema = this.edgeLabel(id); + names.add(schema.name()); + } + return names; + } + + default Set> mapPairId2Name( + Set> pairs) { + Set> results = new HashSet<>(pairs.size()); + for (Pair pair : pairs) { + results.add(Pair.of(this.vertexLabel(pair.getLeft()).name(), + this.vertexLabel(pair.getRight()).name())); + } + return results; + } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java index 4edd2ffa9b..8e7537e072 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/Analyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -23,5 +21,5 @@ public interface Analyzer { - public Set segment(String text); + Set segment(String text); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java index bff18ab7b0..2cf1dc1b03 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnalyzerFactory.java @@ -1,36 +1,33 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; - -import org.apache.hugegraph.exception.HugeException; - import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.hugegraph.exception.HugeException; + public class AnalyzerFactory { - private static Map> analyzers; + private static final Map> ANALYZERS; static { - analyzers = new ConcurrentHashMap<>(); + ANALYZERS = new ConcurrentHashMap<>(); } public static Analyzer analyzer(String name, String mode) { @@ -58,7 +55,7 @@ public static Analyzer analyzer(String name, String mode) { } private static Analyzer customizedAnalyzer(String name, String mode) { - Class clazz = analyzers.get(name); + Class clazz = ANALYZERS.get(name); if (clazz == null) { throw new HugeException("Not exists analyzer: %s", name); } @@ -68,12 +65,12 @@ private static Analyzer customizedAnalyzer(String name, String mode) { return clazz.getConstructor(String.class).newInstance(mode); } catch (Exception e) { throw new HugeException( - "Failed to construct analyzer '%s' with mode '%s'", - e, name, mode); + "Failed to construct analyzer '%s' with mode '%s'", + e, name, mode); } } - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) public static void register(String name, String classPath) { ClassLoader classLoader = AnalyzerFactory.class.getClassLoader(); Class clazz; @@ -91,12 +88,12 @@ public static void register(String name, String classPath) { } // Check exists - if (analyzers.containsKey(name)) { + if (ANALYZERS.containsKey(name)) { throw new HugeException("Exists analyzer: %s(%s)", - name, analyzers.get(name).getName()); + name, ANALYZERS.get(name).getName()); } // Register class - analyzers.put(name, (Class) clazz); + ANALYZERS.put(name, (Class) clazz); } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java index 3f041d31f8..2f857cd171 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/AnsjAnalyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -34,7 +32,7 @@ import com.google.common.collect.ImmutableList; /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://github.com/NLPchina/ansj_seg/wiki */ public class AnsjAnalyzer implements Analyzer { @@ -45,20 +43,20 @@ public class AnsjAnalyzer implements Analyzer { "NlpAnalysis" ); - private String analysis; + private final String analysis; public AnsjAnalyzer(String mode) { if (!SUPPORT_MODES.contains(mode)) { throw new ConfigException( - "Unsupported segment mode '%s' for ansj analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); + "Unsupported segment mode '%s' for ansj analyzer, " + + "the available values are %s", mode, SUPPORT_MODES); } this.analysis = mode; } @Override public Set segment(String text) { - Result terms = null; + Result terms; switch (this.analysis) { case "BaseAnalysis": terms = BaseAnalysis.parse(text); @@ -74,7 +72,7 @@ public Set segment(String text) { break; default: throw new AssertionError(String.format( - "Unsupported segment mode '%s'", this.analysis)); + "Unsupported segment mode '%s'", this.analysis)); } assert terms != null; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java index b8175e400c..8b5fa6aa0a 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/HanLPAnalyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -22,6 +20,8 @@ import java.util.List; import java.util.Set; +import org.apache.hugegraph.config.ConfigException; +import org.apache.hugegraph.util.InsertionOrderUtil; import com.google.common.collect.ImmutableList; import com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment; @@ -33,23 +33,20 @@ import com.hankcs.hanlp.tokenizer.SpeedTokenizer; import com.hankcs.hanlp.tokenizer.StandardTokenizer; -import org.apache.hugegraph.config.ConfigException; -import org.apache.hugegraph.util.InsertionOrderUtil; - /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://github.com/hankcs/HanLP/wiki */ public class HanLPAnalyzer implements Analyzer { public static final List SUPPORT_MODES = - ImmutableList.builder() - .add("standard") - .add("nlp") - .add("index") - .add("nShort") - .add("shortest") - .add("speed") - .build(); + ImmutableList.builder() + .add("standard") + .add("nlp") + .add("index") + .add("nShort") + .add("shortest") + .add("speed") + .build(); private static final Segment N_SHORT_SEGMENT = new NShortSegment().enableCustomDictionary(false) @@ -60,20 +57,20 @@ public class HanLPAnalyzer implements Analyzer { .enablePlaceRecognize(true) .enableOrganizationRecognize(true); - private String tokenizer; + private final String tokenizer; public HanLPAnalyzer(String mode) { if (!SUPPORT_MODES.contains(mode)) { throw new ConfigException( - "Unsupported segment mode '%s' for hanlp analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); + "Unsupported segment mode '%s' for hanlp analyzer, " + + "the available values are %s", mode, SUPPORT_MODES); } this.tokenizer = mode; } @Override public Set segment(String text) { - List terms = null; + List terms; switch (this.tokenizer) { case "standard": terms = StandardTokenizer.segment(text); @@ -95,7 +92,7 @@ public Set segment(String text) { break; default: throw new AssertionError(String.format( - "Unsupported segment mode '%s'", this.tokenizer)); + "Unsupported segment mode '%s'", this.tokenizer)); } assert terms != null; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java index a938e8e01f..bf97437fdd 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/IKAnalyzer.java @@ -1,38 +1,36 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; -import com.google.common.collect.ImmutableList; +import java.io.StringReader; +import java.util.List; +import java.util.Set; -import org.apache.hugegraph.config.ConfigException; import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.config.ConfigException; import org.apache.hugegraph.util.InsertionOrderUtil; import org.wltea.analyzer.core.IKSegmenter; import org.wltea.analyzer.core.Lexeme; -import java.io.StringReader; -import java.util.List; -import java.util.Set; +import com.google.common.collect.ImmutableList; /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://github.com/yyn0210/IKAnalyzer */ public class IKAnalyzer implements Analyzer { @@ -41,26 +39,24 @@ public class IKAnalyzer implements Analyzer { "max_word" ); - private boolean smartSegMode; - private final IKSegmenter ik; + private final boolean smartSegMode; public IKAnalyzer(String mode) { if (!SUPPORT_MODES.contains(mode)) { throw new ConfigException( - "Unsupported segment mode '%s' for ikanalyzer, " + - "the available values are %s", mode, SUPPORT_MODES); + "Unsupported segment mode '%s' for ikanalyzer, " + + "the available values are %s", mode, SUPPORT_MODES); } this.smartSegMode = SUPPORT_MODES.get(0).equals(mode); - this.ik = new IKSegmenter(new StringReader(""), - this.smartSegMode); } @Override public Set segment(String text) { Set result = InsertionOrderUtil.newSet(); - ik.reset(new StringReader(text)); + IKSegmenter ik = new IKSegmenter(new StringReader(text), + this.smartSegMode); try { - Lexeme word = null; + Lexeme word; while ((word = ik.next()) != null) { result.add(word.getLexemeText()); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java index 0a69af8384..7e7b9321bf 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JcsegAnalyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -23,19 +21,19 @@ import java.util.List; import java.util.Set; -import org.apache.hugegraph.config.ConfigException; import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.config.ConfigException; import org.apache.hugegraph.util.InsertionOrderUtil; -import org.lionsoul.jcseg.tokenizer.core.ADictionary; -import org.lionsoul.jcseg.tokenizer.core.DictionaryFactory; -import org.lionsoul.jcseg.tokenizer.core.ISegment; -import org.lionsoul.jcseg.tokenizer.core.IWord; -import org.lionsoul.jcseg.tokenizer.core.JcsegTaskConfig; -import org.lionsoul.jcseg.tokenizer.core.SegmentFactory; +import org.lionsoul.jcseg.ISegment; +import org.lionsoul.jcseg.IWord; +import org.lionsoul.jcseg.dic.ADictionary; +import org.lionsoul.jcseg.dic.DictionaryFactory; +import org.lionsoul.jcseg.segmenter.SegmenterConfig; + import com.google.common.collect.ImmutableList; /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://github.com/lionsoul2014/jcseg */ public class JcsegAnalyzer implements Analyzer { @@ -44,29 +42,34 @@ public class JcsegAnalyzer implements Analyzer { "Complex" ); - private static final JcsegTaskConfig CONFIG = new JcsegTaskConfig(); - private static final ADictionary DIC = - DictionaryFactory.createDefaultDictionary(new JcsegTaskConfig()); + private static final SegmenterConfig CONFIG = new SegmenterConfig(); + private static final ADictionary DIC = DictionaryFactory.createDefaultDictionary(CONFIG); - private int segMode; + private final ISegment.Type type; public JcsegAnalyzer(String mode) { if (!SUPPORT_MODES.contains(mode)) { throw new ConfigException( - "Unsupported segment mode '%s' for jcseg analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); + "Unsupported segment mode '%s' for jcseg analyzer, " + + "the available values are %s", mode, SUPPORT_MODES); + } + + if ("Simple".equals(mode)) { + this.type = ISegment.SIMPLE; + } else { + this.type = ISegment.COMPLEX; } - this.segMode = SUPPORT_MODES.indexOf(mode) + 1; } @Override public Set segment(String text) { Set result = InsertionOrderUtil.newSet(); try { - Object[] args = new Object[]{new StringReader(text), CONFIG, DIC}; - ISegment seg = SegmentFactory.createJcseg(this.segMode, args); - IWord word = null; - while ((word = seg.next()) != null) { + ISegment segmentor = this.type.factory.create(CONFIG, DIC); + segmentor.reset(new StringReader(text)); + + IWord word; + while ((word = segmentor.next()) != null) { result.add(word.getValue()); } } catch (Exception e) { diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java index 70cae33268..7c280a50a1 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/JiebaAnalyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -30,7 +28,7 @@ import com.huaban.analysis.jieba.SegToken; /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://github.com/huaban/jieba-analysis */ public class JiebaAnalyzer implements Analyzer { @@ -41,13 +39,13 @@ public class JiebaAnalyzer implements Analyzer { private static final JiebaSegmenter JIEBA_SEGMENTER = new JiebaSegmenter(); - private JiebaSegmenter.SegMode segMode; + private final JiebaSegmenter.SegMode segMode; public JiebaAnalyzer(String mode) { if (!SUPPORT_MODES.contains(mode)) { throw new ConfigException( - "Unsupported segment mode '%s' for jieba analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); + "Unsupported segment mode '%s' for jieba analyzer, " + + "the available values are %s", mode, SUPPORT_MODES); } this.segMode = JiebaSegmenter.SegMode.valueOf(mode); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java index 3316582f73..a4415911fa 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/MMSeg4JAnalyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -23,10 +21,10 @@ import java.util.List; import java.util.Set; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.config.ConfigException; import org.apache.hugegraph.util.InsertionOrderUtil; -import org.apache.hugegraph.exception.HugeException; import com.chenlb.mmseg4j.ComplexSeg; import com.chenlb.mmseg4j.Dictionary; import com.chenlb.mmseg4j.MMSeg; @@ -37,7 +35,7 @@ import com.google.common.collect.ImmutableList; /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://github.com/chenlb/mmseg4j-core */ public class MMSeg4JAnalyzer implements Analyzer { @@ -49,13 +47,13 @@ public class MMSeg4JAnalyzer implements Analyzer { private static final Dictionary DIC = Dictionary.getInstance(); - private Seg seg; + private final Seg seg; public MMSeg4JAnalyzer(String mode) { if (!SUPPORT_MODES.contains(mode)) { throw new ConfigException( - "Unsupported segment mode '%s' for mmseg4j analyzer, " + - "the available values are %s", mode, SUPPORT_MODES); + "Unsupported segment mode '%s' for mmseg4j analyzer, " + + "the available values are %s", mode, SUPPORT_MODES); } int index = SUPPORT_MODES.indexOf(mode); switch (index) { @@ -70,7 +68,7 @@ public MMSeg4JAnalyzer(String mode) { break; default: throw new AssertionError(String.format( - "Unsupported segment mode '%s'", this.seg)); + "Unsupported segment mode '%s'", mode)); } } @@ -79,7 +77,7 @@ public Set segment(String text) { Set result = InsertionOrderUtil.newSet(); MMSeg mmSeg = new MMSeg(new StringReader(text), this.seg); try { - Word word = null; + Word word; while ((word = mmSeg.next()) != null) { result.add(word.getString()); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java index 34c0ea2fba..7b00aa59dd 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/analyzer/SmartCNAnalyzer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.analyzer; @@ -24,23 +22,23 @@ import java.util.List; import java.util.Set; +import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.util.InsertionOrderUtil; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; -import org.apache.hugegraph.exception.HugeException; import com.google.common.collect.ImmutableList; /** - * Reference from https://my.oschina.net/apdplat/blog/412921 + * Reference from https://lucene.apache.org/core/8_11_2/analyzers-smartcn/index.html */ public class SmartCNAnalyzer implements Analyzer { public static final List SUPPORT_MODES = ImmutableList.of(); private static final SmartChineseAnalyzer ANALYZER = - new SmartChineseAnalyzer(); + new SmartChineseAnalyzer(); public SmartCNAnalyzer(String mode) { // pass @@ -52,7 +50,7 @@ public Set segment(String text) { Reader reader = new StringReader(text); try (TokenStream tokenStream = ANALYZER.tokenStream("text", reader)) { tokenStream.reset(); - CharTermAttribute term = null; + CharTermAttribute term; while (tokenStream.incrementToken()) { term = tokenStream.getAttribute(CharTermAttribute.class); result.add(term.toString()); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/auth/AuthConstant.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/auth/AuthConstant.java deleted file mode 100644 index 97bd1a0e1c..0000000000 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/auth/AuthConstant.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2017 HugeGraph Authors - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.auth; - -public interface AuthConstant { - - /* - * Fields in token - */ - String TOKEN_USER_NAME = "user_name"; - String TOKEN_USER_ID = "user_id"; - String TOKEN_USER_PASSWORD = "user_password"; -} diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/backend/BinaryId.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/backend/BinaryId.java index 685a934fd7..3b72d707cc 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/backend/BinaryId.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/backend/BinaryId.java @@ -1,36 +1,33 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.backend; -import org.apache.hugegraph.id.Id; +import java.nio.ByteBuffer; +import java.util.Arrays; +import org.apache.hugegraph.id.Id; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; -import java.nio.ByteBuffer; -import java.util.Arrays; - -public final class BinaryId implements Id { +public class BinaryId implements Id { - private final byte[] bytes; - private final Id id; + protected byte[] bytes; + protected Id id; public BinaryId(byte[] bytes, Id id) { this.bytes = bytes; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java index d5034b703a..a5777f9fd1 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/ErrorCodeProvider.java @@ -21,7 +21,7 @@ public interface ErrorCodeProvider { - public String format(Object... args); + String format(Object... args); - public String with(String message); + String with(String message); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java index 10652dca2c..6defbf7a44 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java @@ -1,24 +1,24 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.exception; +import org.apache.hugegraph.exception.HugeException; + public class LimitExceedException extends HugeException { private static final long serialVersionUID = 7384276720045597709L; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotAllowException.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotAllowException.java index 3781b6d482..75e4f9b597 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotAllowException.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotAllowException.java @@ -1,24 +1,24 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.exception; +import org.apache.hugegraph.exception.HugeException; + public class NotAllowException extends HugeException { private static final long serialVersionUID = -1407924451828873200L; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotFoundException.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotFoundException.java index 8567ceb018..7eaadd3fb6 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotFoundException.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotFoundException.java @@ -1,24 +1,24 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.exception; +import org.apache.hugegraph.exception.HugeException; + public class NotFoundException extends HugeException { private static final long serialVersionUID = -5912665926327173032L; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotSupportException.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotSupportException.java index 49d3dad49c..713295af70 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotSupportException.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/exception/NotSupportException.java @@ -1,24 +1,24 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.exception; +import org.apache.hugegraph.exception.HugeException; + public class NotSupportException extends HugeException { private static final long serialVersionUID = -2914329541122906234L; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/EdgeId.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/EdgeId.java index 2b03e97d33..dfb530702f 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/EdgeId.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/EdgeId.java @@ -1,50 +1,45 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.id; -import org.apache.hugegraph.perf.PerfUtil.Watched; -import org.apache.hugegraph.testutil.Assert; -import org.apache.hugegraph.util.E; - import org.apache.hugegraph.exception.NotFoundException; +import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.StringEncoding; /** * Class used to format and parse id of edge, the edge id consists of: * EdgeId = { source-vertex-id > direction > parentEdgeLabelId > subEdgeLabelId - * >sortKeys > target-vertex-id } + * > sortKeys > target-vertex-id } * NOTE: - * 1. for edges with edgeLabel-type=NORMAL,edgelabelId=parentEdgeLabelId=subEdgeLabelId, - * for edges with edgeLabel type=PARENT,edgelabelId = subEdgeLabelId , - * parentEdgeLabelId = edgelabelId.fatherId - * - * 2.if we use `entry.type()` which is IN or OUT as a part of id, + *

1. for edges with edgeLabelType = NORMAL: edgeLabelId = parentEdgeLabelId = subEdgeLabelId; + * for edges with edgeLabelType = PARENT: edgeLabelId = subEdgeLabelId, parentEdgeLabelId = + * edgeLabelId.fatherId + *

2.if we use `entry.type()` which is IN or OUT as a part of id, * an edge's id will be different due to different directions (belongs * to 2 owner vertex) */ public class EdgeId implements Id { - public static final HugeKeys[] KEYS = new HugeKeys[] { + public static final HugeKeys[] KEYS = new HugeKeys[]{ HugeKeys.OWNER_VERTEX, HugeKeys.DIRECTION, HugeKeys.LABEL, @@ -53,32 +48,28 @@ public class EdgeId implements Id { HugeKeys.OTHER_VERTEX }; - private final Id ownerVertexId; - private final Directions direction; - private final Id edgeLabelId; - private final Id subLabelId; - private final String sortValues; - private final Id otherVertexId; - - private final boolean directed; - private String cache; - + protected final Id ownerVertexId; + protected final Id edgeLabelId; + protected final Id subLabelId; + protected final Id otherVertexId; + protected final Directions direction; + protected final boolean directed; + protected String sortValues; + protected String cache; - public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, - Id subLabelId, String sortValues, - Id otherVertexId) { - this(ownerVertexId, direction, edgeLabelId, - subLabelId, sortValues, otherVertexId, false); + public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, Id subLabelId, + String sortValues, Id otherVertexId) { + this(ownerVertexId, direction, edgeLabelId, subLabelId, + sortValues, otherVertexId, false); } - public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, - Id subLabelId, String sortValues, - Id otherVertexId, boolean directed) { + public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, Id subLabelId, + String sortValues, Id otherVertexId, boolean directed) { this.ownerVertexId = ownerVertexId; this.direction = direction; this.edgeLabelId = edgeLabelId; - this.sortValues = sortValues; this.subLabelId = subLabelId; + this.sortValues = sortValues; this.otherVertexId = otherVertexId; this.directed = directed; this.cache = null; @@ -87,14 +78,13 @@ public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, @Watched public EdgeId switchDirection() { Directions direction = this.direction.opposite(); - return new EdgeId(this.otherVertexId, direction, this.edgeLabelId, - this.subLabelId, this.sortValues, this.ownerVertexId, - this.directed); + return new EdgeId(this.otherVertexId, direction, this.edgeLabelId, this.subLabelId, + this.sortValues, this.ownerVertexId, this.directed); } public EdgeId directed(boolean directed) { - return new EdgeId(this.ownerVertexId, this.direction, this.edgeLabelId, - this.subLabelId, this.sortValues, this.otherVertexId, directed); + return new EdgeId(this.ownerVertexId, this.direction, this.edgeLabelId, this.subLabelId, + this.sortValues, this.otherVertexId, directed); } private Id sourceVertexId() { @@ -109,10 +99,6 @@ private Id targetVertexId() { this.ownerVertexId; } - public Id subLabelId(){ - return this.subLabelId; - } - public Id ownerVertexId() { return this.ownerVertexId; } @@ -121,6 +107,10 @@ public Id edgeLabelId() { return this.edgeLabelId; } + public Id subLabelId() { + return this.subLabelId; + } + public Directions direction() { return this.direction; } @@ -147,23 +137,34 @@ public String asString() { if (this.cache != null) { return this.cache; } + this.cache = this.formatString(); + return this.cache; + } + + /** + * Format the shared edge identity without retaining a heap cache. Read + * components through accessors so storage adapters can keep them off heap. + */ + protected final String formatString() { + Id owner = this.ownerVertexId(); + Id other = this.otherVertexId(); if (this.directed) { - this.cache = SplicingIdGenerator.concat( - IdUtil.writeString(this.ownerVertexId), - this.direction.type().string(), - IdUtil.writeLong(this.edgeLabelId), - IdUtil.writeLong(this.subLabelId), - this.sortValues, - IdUtil.writeString(this.otherVertexId)); - } else { - this.cache = SplicingIdGenerator.concat( - IdUtil.writeString(this.sourceVertexId()), - IdUtil.writeLong(this.edgeLabelId), - IdUtil.writeLong(this.subLabelId), - this.sortValues, - IdUtil.writeString(this.targetVertexId())); + return SplicingIdGenerator.concat( + IdUtil.writeString(owner), + this.direction().type().string(), + IdUtil.writeLong(this.edgeLabelId()), + IdUtil.writeLong(this.subLabelId()), + this.sortValues(), + IdUtil.writeString(other)); } - return this.cache; + Id source = this.direction() == Directions.OUT ? owner : other; + Id target = this.direction() == Directions.OUT ? other : owner; + return SplicingIdGenerator.concat( + IdUtil.writeString(source), + IdUtil.writeLong(this.edgeLabelId()), + IdUtil.writeLong(this.subLabelId()), + this.sortValues(), + IdUtil.writeString(target)); } @Override @@ -219,14 +220,14 @@ public boolean equals(Object object) { return this.ownerVertexId.equals(other.ownerVertexId) && this.direction == other.direction && this.edgeLabelId.equals(other.edgeLabelId) && - this.sortValues.equals(other.sortValues) && this.subLabelId.equals(other.subLabelId) && + this.sortValues.equals(other.sortValues) && this.otherVertexId.equals(other.otherVertexId); } else { return this.sourceVertexId().equals(other.sourceVertexId()) && this.edgeLabelId.equals(other.edgeLabelId) && - this.sortValues.equals(other.sortValues) && this.subLabelId.equals(other.subLabelId) && + this.sortValues.equals(other.sortValues) && this.targetVertexId().equals(other.targetVertexId()); } } @@ -241,7 +242,7 @@ public static byte directionToCode(Directions direction) { } public static Directions directionFromCode(byte code) { - return (code == HugeType.EDGE_OUT.code()) ? Directions.OUT : Directions.IN; + return Directions.convert(HugeType.fromCode(code)); } public static boolean isOutDirectionFromCode(byte code) { @@ -253,7 +254,7 @@ public static EdgeId parse(String id) throws NotFoundException { } public static EdgeId parse(String id, boolean returnNullIfError) - throws NotFoundException { + throws NotFoundException { String[] idParts = SplicingIdGenerator.split(id); if (!(idParts.length == 5 || idParts.length == 6)) { if (returnNullIfError) { @@ -270,8 +271,8 @@ public static EdgeId parse(String id, boolean returnNullIfError) Id subLabelId = IdUtil.readLong(idParts[2]); String sortValues = idParts[3]; Id otherVertexId = IdUtil.readString(idParts[4]); - return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, - subLabelId, sortValues, otherVertexId); + return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, subLabelId, + sortValues, otherVertexId); } else { assert idParts.length == 6; Id ownerVertexId = IdUtil.readString(idParts[0]); @@ -281,8 +282,7 @@ public static EdgeId parse(String id, boolean returnNullIfError) String sortValues = idParts[4]; Id otherVertexId = IdUtil.readString(idParts[5]); return new EdgeId(ownerVertexId, Directions.convert(direction), - edgeLabelId, subLabelId, - sortValues, otherVertexId); + edgeLabelId, subLabelId, sortValues, otherVertexId); } } catch (Throwable e) { if (returnNullIfError) { @@ -301,8 +301,8 @@ public static Id parseStoredString(String id) { Id subLabelId = IdGenerator.ofStoredString(idParts[2], IdType.LONG); String sortValues = idParts[3]; Id otherVertexId = IdUtil.readStoredString(idParts[4]); - return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, - subLabelId, sortValues, otherVertexId); + return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, subLabelId, + sortValues, otherVertexId); } public static String asStoredString(Id id) { @@ -326,25 +326,4 @@ public static String[] split(Id id) { public static String[] split(String id) { return SplicingIdGenerator.split(id); } - - - public static void main(String[] args) { - EdgeId edgeId1 = new EdgeId(IdGenerator.of("1:marko"), Directions.OUT, - IdGenerator.of(1), - IdGenerator.of(1), "", - IdGenerator.of("1:josh")); - EdgeId edgeId2 = new EdgeId(IdGenerator.of("1:marko"), Directions.OUT, - IdGenerator.of(1), - IdGenerator.of(1), "", - IdGenerator.of("1:josh")); - EdgeId edgeId3 = new EdgeId(IdGenerator.of("1:josh"), Directions.IN, - IdGenerator.of(1), - IdGenerator.of(1), "", - IdGenerator.of("1:marko")); - Assert.assertTrue(edgeId1.equals(edgeId2)); - Assert.assertTrue(edgeId2.equals(edgeId1)); - Assert.assertTrue(edgeId1.equals(edgeId3)); - Assert.assertTrue(edgeId3.equals(edgeId1)); - } - } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/Id.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/Id.java index aeb7810a9d..89f61d9583 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/Id.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/Id.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.id; @@ -25,37 +23,37 @@ public interface Id extends Comparable, Serializable { - public static final int UUID_LENGTH = 16; + int UUID_LENGTH = 16; - public Object asObject(); + Object asObject(); - public String asString(); + String asString(); - public long asLong(); + long asLong(); - public byte[] asBytes(); + byte[] asBytes(); - public int length(); + int length(); - public IdType type(); + IdType type(); - public default boolean number() { + default boolean number() { return this.type() == IdType.LONG; } - public default boolean uuid() { + default boolean uuid() { return this.type() == IdType.UUID; } - public default boolean string() { + default boolean string() { return this.type() == IdType.STRING; } - public default boolean edge() { + default boolean edge() { return this.type() == IdType.EDGE; } - public enum IdType { + enum IdType { UNKNOWN, LONG, @@ -71,8 +69,7 @@ public char prefix() { } public static IdType valueOfPrefix(String id) { - E.checkArgument(id != null && id.length() > 0, - "Invalid id '%s'", id); + E.checkArgument(id != null && !id.isEmpty(), "Invalid id '%s'", id); switch (id.charAt(0)) { case 'L': return IdType.LONG; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java index b6687262db..a56eb0e236 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java @@ -1,36 +1,33 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.id; +import java.util.Objects; +import java.util.UUID; + +import org.apache.hugegraph.id.Id.IdType; import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.structure.BaseVertex; -import org.apache.hugegraph.util.StringEncoding; -import com.google.common.primitives.Longs; - +import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.LongEncoding; import org.apache.hugegraph.util.NumericUtil; - -import java.nio.charset.Charset; -import java.util.Objects; -import java.util.UUID; +import org.apache.hugegraph.util.StringEncoding; public abstract class IdGenerator { @@ -38,19 +35,19 @@ public abstract class IdGenerator { public abstract Id generate(BaseVertex vertex); - public final static Id of(String id) { + public static Id of(String id) { return new StringId(id); } - public final static Id of(UUID id) { + public static Id of(UUID id) { return new UuidId(id); } - public final static Id of(String id, boolean uuid) { + public static Id of(String id, boolean uuid) { return uuid ? new UuidId(id) : new StringId(id); } - public final static Id of(long id) { + public static Id of(long id) { return new LongId(id); } @@ -67,7 +64,7 @@ public static Id of(Object id) { return new ObjectId(id); } - public final static Id of(byte[] bytes, Id.IdType type) { + public static Id of(byte[] bytes, IdType type) { switch (type) { case LONG: return new LongId(bytes); @@ -80,13 +77,13 @@ public final static Id of(byte[] bytes, Id.IdType type) { } } - public final static Id ofStoredString(String id, Id.IdType type) { + public static Id ofStoredString(String id, IdType type) { switch (type) { case LONG: return of(LongEncoding.decodeSignedB64(id)); case UUID: byte[] bytes = StringEncoding.decodeBase64(id); - return of(bytes, Id.IdType.UUID); + return of(bytes, IdType.UUID); case STRING: return of(id); default: @@ -94,7 +91,7 @@ public final static Id ofStoredString(String id, Id.IdType type) { } } - public final static String asStoredString(Id id) { + public static String asStoredString(Id id) { switch (id.type()) { case LONG: return LongEncoding.encodeSignedB64(id.asLong()); @@ -107,40 +104,45 @@ public final static String asStoredString(Id id) { } } - public final static Id.IdType idType(Id id) { + public static IdType idType(Id id) { if (id instanceof LongId) { - return Id.IdType.LONG; + return IdType.LONG; } if (id instanceof UuidId) { - return Id.IdType.UUID; + return IdType.UUID; } if (id instanceof StringId) { - return Id.IdType.STRING; + return IdType.STRING; } if (id instanceof EdgeId) { - return Id.IdType.EDGE; + return IdType.EDGE; } - return Id.IdType.UNKNOWN; + return IdType.UNKNOWN; } - private final static int compareType(Id id1, Id id2) { + public static int compareType(Id id1, Id id2) { return idType(id1).ordinal() - idType(id2).ordinal(); } /****************************** id defines ******************************/ - public static final class StringId implements Id { + public static class StringId implements Id { - private final String id; - private static final Charset CHARSET = Charset.forName("UTF-8"); + protected String id; + protected byte[] bytes; public StringId(String id) { - E.checkArgument(!id.isEmpty(), "The id can't be empty"); + E.checkArgument(id != null && !id.isEmpty(), + "The id can't be null or empty"); this.id = id; + this.bytes = null; } public StringId(byte[] bytes) { - this.id = StringEncoding.decode(bytes); + E.checkArgument(bytes != null && bytes.length > 0, + "The id bytes can't be null or empty"); + this.bytes = bytes; + this.id = null; } @Override @@ -150,27 +152,35 @@ public IdType type() { @Override public Object asObject() { - return this.id; + return this.asString(); } @Override public String asString() { + if (this.id == null) { + assert this.bytes != null; + this.id = StringEncoding.decode(this.bytes); + } return this.id; } @Override public long asLong() { - return Long.parseLong(this.id); + return Long.parseLong(this.asString()); } @Override public byte[] asBytes() { - return this.id.getBytes(CHARSET); + if (this.bytes == null) { + assert this.id != null; + this.bytes = StringEncoding.encode(this.id); + } + return this.bytes; } @Override public int length() { - return this.id.length(); + return this.asString().length(); } @Override @@ -179,33 +189,45 @@ public int compareTo(Id other) { if (cmp != 0) { return cmp; } - return this.id.compareTo(other.asString()); + if (this.id != null) { + return this.id.compareTo(other.asString()); + } else { + return Bytes.compare(this.bytes, other.asBytes()); + } } @Override public int hashCode() { - return this.id.hashCode(); + return this.asString().hashCode(); } @Override - public boolean equals(Object other) { - if (!(other instanceof StringId)) { + public boolean equals(Object obj) { + if (!(obj instanceof StringId)) { return false; } - return this.id.equals(((StringId) other).id); + StringId other = (StringId) obj; + if (this.id != null) { + return this.id.equals(other.asString()); + } else if (other.bytes == null) { + return this.asString().equals(other.asString()); + } else { + assert this.bytes != null; + return Bytes.equals(this.bytes, other.asBytes()); + } } @Override public String toString() { - return this.id; + return this.asString(); } } - public static final class LongId extends Number implements Id { + public static class LongId extends Number implements Id { private static final long serialVersionUID = -7732461469037400190L; - private final long id; + protected Long id; public LongId(long id) { this.id = id; @@ -238,8 +260,7 @@ public long asLong() { @Override public byte[] asBytes() { - return Longs.toByteArray(this.id); - // return NumericUtil.longToBytes(this.id); + return NumericUtil.longToBytes(this.id); } @Override @@ -264,26 +285,11 @@ public int hashCode() { @Override public boolean equals(Object other) { if (!(other instanceof Number)) { - if (idDigitalObject(other)) { - return this.id == (long) Double.parseDouble(other.toString()); - } return false; } return this.id == ((Number) other).longValue(); } - private static boolean idDigitalObject(Object object) { - String string = object.toString(); - for (int i = string.length(); --i >= 0; ) { - char c = string.charAt(i); - if (!Character.isDigit(c) && - '.' != c) { - return false; - } - } - return true; - } - @Override public String toString() { return String.valueOf(this.id); @@ -291,7 +297,7 @@ public String toString() { @Override public int intValue() { - return (int) this.id; + return this.id.intValue(); } @Override @@ -310,9 +316,9 @@ public double doubleValue() { } } - public static final class UuidId implements Id { + public static class UuidId implements Id { - private final UUID uuid; + protected UUID uuid; public UuidId(String string) { this(StringEncoding.uuid(string)); @@ -400,9 +406,9 @@ public String toString() { /** * This class is just used by backend store for wrapper object as Id */ - public static final class ObjectId implements Id { + public static class ObjectId implements Id { - private final Object object; + protected Object object; public ObjectId(Object object) { E.checkNotNull(object, "object"); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdUtil.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdUtil.java index b394c79a12..ce7c970edc 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdUtil.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdUtil.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.id; @@ -22,7 +20,7 @@ import java.nio.ByteBuffer; import org.apache.commons.lang3.StringUtils; - +import org.apache.hugegraph.id.Id.IdType; import org.apache.hugegraph.serializer.BytesBuffer; public final class IdUtil { @@ -45,7 +43,7 @@ public static String writeStoredString(Id id) { } public static Id readStoredString(String id) { - Id.IdType type = Id.IdType.valueOfPrefix(id); + IdType type = IdType.valueOfPrefix(id); String idContent = id.substring(1); switch (type) { case LONG: @@ -82,23 +80,20 @@ public static Id fromBytes(byte[] bytes) { return buffer.readId(); } - public static String writeString(Id id) { String idString = id.asString(); - StringBuilder sb = new StringBuilder(1 + idString.length()); - sb.append(id.type().prefix()).append(idString); - return sb.toString(); + return id.type().prefix() + idString; } public static Id readString(String id) { - Id.IdType type = Id.IdType.valueOfPrefix(id); + IdType type = IdType.valueOfPrefix(id); String idContent = id.substring(1); switch (type) { case LONG: return IdGenerator.of(Long.parseLong(idContent)); case STRING: case UUID: - return IdGenerator.of(idContent, type == Id.IdType.UUID); + return IdGenerator.of(idContent, type == IdType.UUID); case EDGE: return EdgeId.parse(idContent); default: @@ -145,12 +140,13 @@ public static String escape(char splitor, char escape, String... values) { public static String[] unescape(String id, String splitor, String escape) { /* - * Note that the `splitor`/`escape` maybe special characters in regular + * Note that the `splitter`/`escape` maybe special characters in regular * expressions, but this is a frequently called method, for faster * execution, we forbid the use of special characters as delimiter * or escape sign. + * * The `limit` param -1 in split method can ensure empty string be - * splited to a part. + * split to a part. */ String[] parts = id.split("(? values) { // Convert the object list to string array @@ -108,8 +109,9 @@ public static String concatValues(List values) { /** * Concat property values with NAME_SPLITOR + * * @param values the property values to be concatted - * @return concatted string value + * @return concatted string value */ public static String concatValues(Object... values) { return concatValues(Arrays.asList(values)); @@ -117,8 +119,9 @@ public static String concatValues(Object... values) { /** * Concat multiple parts into a single id with ID_SPLITOR + * * @param parts the string id values to be spliced - * @return spliced id object + * @return spliced id object */ public static Id splicing(String... parts) { String escaped = IdUtil.escape(ID_SPLITOR, ESCAPE, parts); @@ -141,8 +144,9 @@ public static Id generateBinaryId(Id id) { /** * Parse a single id into multiple parts with ID_SPLITOR + * * @param id the id object to be parsed - * @return parsed string id parts + * @return parsed string id parts */ public static String[] parse(Id id) { return IdUtil.unescape(id.asString(), ID_SPLITOR_STR, ESCAPE_STR); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/options/AuthOptions.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/options/AuthOptions.java deleted file mode 100644 index 27bbb963b5..0000000000 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/options/AuthOptions.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2017 HugeGraph Authors - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package org.apache.hugegraph.options; - -import org.apache.hugegraph.config.ConfigOption; -import org.apache.hugegraph.config.OptionHolder; - -import static org.apache.hugegraph.config.OptionChecker.*; - -public class AuthOptions extends OptionHolder { - - private AuthOptions() { - super(); - } - - private static volatile AuthOptions instance; - - public static synchronized AuthOptions instance() { - if (instance == null) { - instance = new AuthOptions(); - instance.registerOptions(); - } - return instance; - } - - public static final ConfigOption AUTH_AUDIT_LOG_RATE = - new ConfigOption<>( - "auth.audit_log_rate", - "The max rate of audit log output per user, " + - "default value is 1000 records per second.", - rangeDouble(0.0, Double.MAX_VALUE), - 1000.0 - ); - - public static final ConfigOption AUTH_PROXY_CACHE_EXPIRE = - new ConfigOption<>( - "auth.proxy_cache_expire", - "The expiration time in seconds of auth cache in " + - "auth client.", - rangeInt(0L, Long.MAX_VALUE), - (1 * 60L) - ); - - public static final ConfigOption AUTH_CACHE_CAPACITY = - new ConfigOption<>( - "auth.cache_capacity", - "The max cache capacity of each auth cache item.", - rangeInt(0L, Long.MAX_VALUE), - (1024 * 10L) - ); - - public static final ConfigOption AUTHENTICATOR = - new ConfigOption<>( - "auth.authenticator", - "The class path of authenticator implementation. " + - "e.g., org.apache.hugegraph.auth.StandardAuthenticator.", - null, - "" - ); - - public static final ConfigOption AUTH_GRAPH_STORE = - new ConfigOption<>( - "auth.graph_store", - "The name of graph used to store authentication information, " + - "like users, only for org.apache.hugegraph.auth.StandardAuthenticator.", - disallowEmpty(), - "hugegraph" - ); - - public static final ConfigOption AUTH_REMOTE_URL = - new ConfigOption<>( - "auth.remote_url", - "If the address is empty, it provide auth service, " + - "otherwise it is auth client and also provide auth service " + - "through rpc forwarding. The remote url can be set to " + - "multiple addresses, which are concat by ','.", - null, - "" - ); - - public static final ConfigOption AUTH_CACHE_EXPIRE = - new ConfigOption<>( - "auth.cache_expire", - "The expiration time in seconds of auth cache in " + - "auth client and auth server.", - rangeInt(0L, Long.MAX_VALUE), - (60 * 10L) - ); - - public static final ConfigOption AUTH_TOKEN_EXPIRE = - new ConfigOption<>( - "auth.token_expire", - "The expiration time in seconds after token created", - rangeInt(0L, Long.MAX_VALUE), - (3600 * 24L) - ); -} diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/options/CoreOptions.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/options/CoreOptions.java deleted file mode 100644 index e11f76d349..0000000000 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/options/CoreOptions.java +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph.options; - -import org.apache.hugegraph.config.ConfigConvOption; -import org.apache.hugegraph.config.ConfigOption; -import org.apache.hugegraph.config.OptionHolder; -import org.apache.hugegraph.query.Query; -import org.apache.hugegraph.type.define.CollectionType; -import org.apache.hugegraph.util.Bytes; - -import static org.apache.hugegraph.config.OptionChecker.*; -import static org.apache.hugegraph.query.Query.COMMIT_BATCH; - -public class CoreOptions extends OptionHolder { - - public static final int CPUS = Runtime.getRuntime().availableProcessors(); - public static final ConfigOption GREMLIN_GRAPH = - new ConfigOption<>( - "gremlin.graph", - "Gremlin entrance to create graph.", - disallowEmpty(), - "org.apache.hugegraph.HugeFactory" - ); - public static final ConfigOption BACKEND = - new ConfigOption<>( - "backend", - "The data store type.", - disallowEmpty(), - "memory" - ); - public static final ConfigOption STORE = - new ConfigOption<>( - "store", - "The backend database name.", - disallowEmpty(), - "hugegraph" - ); - public static final ConfigOption STORE_GRAPH = - new ConfigOption<>( - "store.graph", - "The graph table name, which store vertex, edge and property.", - disallowEmpty(), - "g" - ); - public static final ConfigOption ALIAS_NAME = - new ConfigOption<>( - "alias.graph.id", - "The graph alias id.", - "" - ); - public static final ConfigOption SERIALIZER = - new ConfigOption<>( - "serializer", - "The serializer for backend store, like: text/binary.", - disallowEmpty(), - "text" - ); - public static final ConfigOption RAFT_MODE = - new ConfigOption<>( - "raft.mode", - "Whether the backend storage works in raft mode.", - disallowEmpty(), - false - ); - public static final ConfigOption RAFT_SAFE_READ = - new ConfigOption<>( - "raft.safe_read", - "Whether to use linearly consistent read.", - disallowEmpty(), - false - ); - public static final ConfigOption RAFT_PATH = - new ConfigOption<>( - "raft.path", - "The log path of current raft node.", - disallowEmpty(), - "./raftlog" - ); - public static final ConfigOption RAFT_REPLICATOR_PIPELINE = - new ConfigOption<>( - "raft.use_replicator_pipeline", - "Whether to use replicator line, when turned on it " + - "multiple logs can be sent in parallel, and the next log " + - "doesn't have to wait for the ack message of the current " + - "log to be sent.", - disallowEmpty(), - true - ); - public static final ConfigOption RAFT_ELECTION_TIMEOUT = - new ConfigOption<>( - "raft.election_timeout", - "Timeout in milliseconds to launch a round of election.", - rangeInt(0, Integer.MAX_VALUE), - 10000 - ); - public static final ConfigOption RAFT_SNAPSHOT_INTERVAL = - new ConfigOption<>( - "raft.snapshot_interval", - "The interval in seconds to trigger snapshot save.", - rangeInt(0, Integer.MAX_VALUE), - 3600 - ); - public static final ConfigOption RAFT_SNAPSHOT_THREADS = - new ConfigOption<>( - "raft.snapshot_threads", - "The thread number used to do snapshot.", - rangeInt(0, Integer.MAX_VALUE), - 4 - ); - public static final ConfigOption RAFT_SNAPSHOT_PARALLEL_COMPRESS = - new ConfigOption<>( - "raft.snapshot_parallel_compress", - "Whether to enable parallel compress.", - disallowEmpty(), - false - ); - public static final ConfigOption RAFT_SNAPSHOT_COMPRESS_THREADS = - new ConfigOption<>( - "raft.snapshot_compress_threads", - "The thread number used to do snapshot compress.", - rangeInt(0, Integer.MAX_VALUE), - 4 - ); - public static final ConfigOption RAFT_SNAPSHOT_DECOMPRESS_THREADS = - new ConfigOption<>( - "raft.snapshot_decompress_threads", - "The thread number used to do snapshot decompress.", - rangeInt(0, Integer.MAX_VALUE), - 4 - ); - public static final ConfigOption RAFT_BACKEND_THREADS = - new ConfigOption<>( - "raft.backend_threads", - "The thread number used to apply task to backend.", - rangeInt(0, Integer.MAX_VALUE), - CPUS - ); - public static final ConfigOption RAFT_READ_INDEX_THREADS = - new ConfigOption<>( - "raft.read_index_threads", - "The thread number used to execute reading index.", - rangeInt(0, Integer.MAX_VALUE), - 8 - ); - public static final ConfigOption RAFT_READ_STRATEGY = - new ConfigOption<>( - "raft.read_strategy", - "The linearizability of read strategy.", - allowValues("ReadOnlyLeaseBased", "ReadOnlySafe"), - "ReadOnlyLeaseBased" - ); - public static final ConfigOption RAFT_APPLY_BATCH = - new ConfigOption<>( - "raft.apply_batch", - "The apply batch size to trigger disruptor event handler.", - positiveInt(), - // jraft default value is 32 - 1 - ); - public static final ConfigOption RAFT_QUEUE_SIZE = - new ConfigOption<>( - "raft.queue_size", - "The disruptor buffers size for jraft RaftNode, " + - "StateMachine and LogManager.", - positiveInt(), - // jraft default value is 16384 - 16384 - ); - public static final ConfigOption RAFT_QUEUE_PUBLISH_TIMEOUT = - new ConfigOption<>( - "raft.queue_publish_timeout", - "The timeout in second when publish event into disruptor.", - positiveInt(), - // jraft default value is 10(sec) - 60 - ); - public static final ConfigOption RAFT_RPC_THREADS = - new ConfigOption<>( - "raft.rpc_threads", - "The rpc threads for jraft RPC layer", - positiveInt(), - // jraft default value is 80 - Math.max(CPUS * 2, 80) - ); - public static final ConfigOption RAFT_RPC_CONNECT_TIMEOUT = - new ConfigOption<>( - "raft.rpc_connect_timeout", - "The rpc connect timeout for jraft rpc.", - positiveInt(), - // jraft default value is 1000(ms) - 5000 - ); - public static final ConfigOption RAFT_RPC_TIMEOUT = - new ConfigOption<>( - "raft.rpc_timeout", - "The general rpc timeout in seconds for jraft rpc.", - positiveInt(), - // jraft default value is 5s - 60 - ); - public static final ConfigOption RAFT_INSTALL_SNAPSHOT_TIMEOUT = - new ConfigOption<>( - "raft.install_snapshot_rpc_timeout", - "The install snapshot rpc timeout in seconds for jraft rpc.", - positiveInt(), - // jraft default value is 5 minutes - 10 * 60 * 60 - ); - public static final ConfigOption RAFT_RPC_BUF_LOW_WATER_MARK = - new ConfigOption<>( - "raft.rpc_buf_low_water_mark", - "The ChannelOutboundBuffer's low water mark of netty, " + - "when buffer size less than this size, the method " + - "ChannelOutboundBuffer.isWritable() will return true, " + - "it means that low downstream pressure or good network.", - positiveInt(), - 10 * 1024 * 1024 - ); - public static final ConfigOption RAFT_RPC_BUF_HIGH_WATER_MARK = - new ConfigOption<>( - "raft.rpc_buf_high_water_mark", - "The ChannelOutboundBuffer's high water mark of netty, " + - "only when buffer size exceed this size, the method " + - "ChannelOutboundBuffer.isWritable() will return false, " + - "it means that the downstream pressure is too great to " + - "process the request or network is very congestion, " + - "upstream needs to limit rate at this time.", - positiveInt(), - 20 * 1024 * 1024 - ); - public static final ConfigOption RATE_LIMIT_WRITE = - new ConfigOption<>( - "rate_limit.write", - "The max rate(items/s) to add/update/delete vertices/edges.", - rangeInt(0, Integer.MAX_VALUE), - 0 - ); - public static final ConfigOption RATE_LIMIT_READ = - new ConfigOption<>( - "rate_limit.read", - "The max rate(times/s) to execute query of vertices/edges.", - rangeInt(0, Integer.MAX_VALUE), - 0 - ); - public static final ConfigOption TASK_SCHEDULE_PERIOD = - new ConfigOption<>( - "task.schedule_period", - "Period time when scheduler to schedule task", - rangeInt(0L, Long.MAX_VALUE), - 10L - ); - public static final ConfigOption TASK_WAIT_TIMEOUT = - new ConfigOption<>( - "task.wait_timeout", - "Timeout in seconds for waiting for the task to " + - "complete, such as when truncating or clearing the " + - "backend.", - rangeInt(0L, Long.MAX_VALUE), - 10L - ); - public static final ConfigOption TASK_INPUT_SIZE_LIMIT = - new ConfigOption<>( - "task.input_size_limit", - "The job input size limit in bytes.", - rangeInt(0L, Bytes.GB), - 16 * Bytes.MB - ); - public static final ConfigOption TASK_RESULT_SIZE_LIMIT = - new ConfigOption<>( - "task.result_size_limit", - "The job result size limit in bytes.", - rangeInt(0L, Bytes.GB), - 16 * Bytes.MB - ); - public static final ConfigOption TASK_TTL_DELETE_BATCH = - new ConfigOption<>( - "task.ttl_delete_batch", - "The batch size used to delete expired data.", - rangeInt(1, 500), - 1 - ); - - public static final ConfigOption TASK_SYNC_DELETION = - new ConfigOption<>( - "task.sync_deletion", - "Whether to delete schema or expired data synchronously.", - disallowEmpty(), - false - ); - public static final ConfigOption TASK_RETRY = - new ConfigOption<>( - "task.retry", - "Task retry times.", - rangeInt(0, 3), - 0 - ); - public static final ConfigOption STORE_CONN_DETECT_INTERVAL = - new ConfigOption<>( - "store.connection_detect_interval", - "The interval in seconds for detecting connections, " + - "if the idle time of a connection exceeds this value, " + - "detect it and reconnect if needed before using, " + - "value 0 means detecting every time.", - rangeInt(0L, Long.MAX_VALUE), - 600L - ); - public static final ConfigOption VERTEX_DEFAULT_LABEL = - new ConfigOption<>( - "vertex.default_label", - "The default vertex label.", - disallowEmpty(), - "vertex" - ); - public static final ConfigOption VERTEX_CHECK_CUSTOMIZED_ID_EXIST = - new ConfigOption<>( - "vertex.check_customized_id_exist", - "Whether to check the vertices exist for those using " + - "customized id strategy.", - disallowEmpty(), - false - ); - public static final ConfigOption VERTEX_REMOVE_LEFT_INDEX = - new ConfigOption<>( - "vertex.remove_left_index_at_overwrite", - "Whether remove left index at overwrite.", - disallowEmpty(), - false - ); - public static final ConfigOption VERTEX_ADJACENT_VERTEX_EXIST = - new ConfigOption<>( - "vertex.check_adjacent_vertex_exist", - "Whether to check the adjacent vertices of edges exist.", - disallowEmpty(), - false - ); - public static final ConfigOption VERTEX_ADJACENT_VERTEX_LAZY = - new ConfigOption<>( - "vertex.lazy_load_adjacent_vertex", - "Whether to lazy load adjacent vertices of edges.", - disallowEmpty(), - true - ); - public static final ConfigOption VERTEX_PART_EDGE_COMMIT_SIZE = - new ConfigOption<>( - "vertex.part_edge_commit_size", - "Whether to enable the mode to commit part of edges of " + - "vertex, enabled if commit size > 0, 0 meas disabled.", - rangeInt(0, (int) Query.DEFAULT_CAPACITY), - 5000 - ); - public static final ConfigOption VERTEX_ENCODE_PK_NUMBER = - new ConfigOption<>( - "vertex.encode_primary_key_number", - "Whether to encode number value of primary key " + - "in vertex id.", - disallowEmpty(), - true - ); - public static final ConfigOption VERTEX_TX_CAPACITY = - new ConfigOption<>( - "vertex.tx_capacity", - "The max size(items) of vertices(uncommitted) in " + - "transaction.", - rangeInt((int) COMMIT_BATCH, 1000000), - 10000 - ); - public static final ConfigOption QUERY_IGNORE_INVALID_DATA = - new ConfigOption<>( - "query.ignore_invalid_data", - "Whether to ignore invalid data of vertex or edge.", - disallowEmpty(), - true - ); - public static final ConfigOption QUERY_OPTIMIZE_AGGR_BY_INDEX = - new ConfigOption<>( - "query.optimize_aggregate_by_index", - "Whether to optimize aggregate query(like count) by index.", - disallowEmpty(), - false - ); - public static final ConfigOption QUERY_BATCH_SIZE = - new ConfigOption<>( - "query.batch_size", - "The size of each batch when querying by batch.", - rangeInt(1, (int) Query.DEFAULT_CAPACITY), - 1000 - ); - public static final ConfigOption QUERY_PAGE_SIZE = - new ConfigOption<>( - "query.page_size", - "The size of each page when querying by paging.", - rangeInt(1, (int) Query.DEFAULT_CAPACITY), - 500 - ); - public static final ConfigOption QUERY_INDEX_INTERSECT_THRESHOLD = - new ConfigOption<>( - "query.index_intersect_threshold", - "The maximum number of intermediate results to " + - "intersect indexes when querying by multiple single " + - "index properties.", - rangeInt(1, (int) Query.DEFAULT_CAPACITY), - 1000 - ); - public static final ConfigOption SCHEMA_INIT_TEMPLATE = - new ConfigOption<>( - "schema.init_template", - "The template schema used to init graph", - null, - "" - ); - public static final ConfigOption SCHEMA_INDEX_REBUILD_USING_PUSHDOWN = - new ConfigOption<>( - "schema.index_rebuild_using_pushdown", - "Whether to use pushdown when to create/rebuid index.", - true - ); - public static final ConfigOption QUERY_RAMTABLE_ENABLE = - new ConfigOption<>( - "query.ramtable_enable", - "Whether to enable ramtable for query of adjacent edges.", - disallowEmpty(), - false - ); - public static final ConfigOption QUERY_RAMTABLE_VERTICES_CAPACITY = - new ConfigOption<>( - "query.ramtable_vertices_capacity", - "The maximum number of vertices in ramtable, " + - "generally the largest vertex id is used as capacity.", - rangeInt(1L, Integer.MAX_VALUE * 2L), - 10000000L - ); - public static final ConfigOption QUERY_RAMTABLE_EDGES_CAPACITY = - new ConfigOption<>( - "query.ramtable_edges_capacity", - "The maximum number of edges in ramtable, " + - "include OUT and IN edges.", - rangeInt(1, Integer.MAX_VALUE), - 20000000 - ); - /** - * The schema name rule: - * 1. Not allowed end with spaces - * 2. Not allowed start with '~' - */ - public static final ConfigOption SCHEMA_ILLEGAL_NAME_REGEX = - new ConfigOption<>( - "schema.illegal_name_regex", - "The regex specified the illegal format for schema name.", - disallowEmpty(), - ".*\\s+$|~.*" - ); - public static final ConfigOption SCHEMA_CACHE_CAPACITY = - new ConfigOption<>( - "schema.cache_capacity", - "The max cache size(items) of schema cache.", - rangeInt(0L, Long.MAX_VALUE), - 10000L - ); - public static final ConfigOption VERTEX_CACHE_TYPE = - new ConfigOption<>( - "vertex.cache_type", - "The type of vertex cache, allowed values are [l1, l2].", - allowValues("l1", "l2"), - "l2" - ); - public static final ConfigOption VERTEX_CACHE_CAPACITY = - new ConfigOption<>( - "vertex.cache_capacity", - "The max cache size(items) of vertex cache.", - rangeInt(0L, Long.MAX_VALUE), - (1000 * 1000 * 10L) - ); - public static final ConfigOption VERTEX_CACHE_EXPIRE = - new ConfigOption<>( - "vertex.cache_expire", - "The expiration time in seconds of vertex cache.", - rangeInt(0, Integer.MAX_VALUE), - (60 * 10) - ); - public static final ConfigOption EDGE_CACHE_TYPE = - new ConfigOption<>( - "edge.cache_type", - "The type of edge cache, allowed values are [l1, l2].", - allowValues("l1", "l2"), - "l2" - ); - public static final ConfigOption EDGE_CACHE_CAPACITY = - new ConfigOption<>( - "edge.cache_capacity", - "The max cache size(items) of edge cache.", - rangeInt(0L, Long.MAX_VALUE), - ((long) 1000 * 1000) - ); - public static final ConfigOption EDGE_CACHE_EXPIRE = - new ConfigOption<>( - "edge.cache_expire", - "The expiration time in seconds of edge cache.", - rangeInt(0, Integer.MAX_VALUE), - (60 * 10) - ); - public static final ConfigOption SNOWFLAKE_WORKER_ID = - new ConfigOption<>( - "snowflake.worker_id", - "The worker id of snowflake id generator.", - disallowEmpty(), - 0L - ); - public static final ConfigOption SNOWFLAKE_DATACENTER_ID = - new ConfigOption<>( - "snowflake.datacenter_id", - "The datacenter id of snowflake id generator.", - disallowEmpty(), - 0L - ); - public static final ConfigOption SNOWFLAKE_FORCE_STRING = - new ConfigOption<>( - "snowflake.force_string", - "Whether to force the snowflake long id to be a string.", - disallowEmpty(), - false - ); - public static final ConfigOption TEXT_ANALYZER = - new ConfigOption<>( - "search.text_analyzer", - "Choose a text analyzer for searching the " + - "vertex/edge properties, available type are " + - "[ansj, hanlp, smartcn, jieba, jcseg, " + - "mmseg4j, ikanalyzer].", - disallowEmpty(), - "ikanalyzer" - ); - public static final ConfigOption TEXT_ANALYZER_MODE = - new ConfigOption<>( - "search.text_analyzer_mode", - "Specify the mode for the text analyzer, " + - "the available mode of analyzer are " + - "ansj: [BaseAnalysis, IndexAnalysis, ToAnalysis, " + - "NlpAnalysis], " + - "hanlp: [standard, nlp, index, nShort, shortest, speed], " + - "smartcn: [], " + - "jieba: [SEARCH, INDEX], " + - "jcseg: [Simple, Complex], " + - "mmseg4j: [Simple, Complex, MaxWord], " + - "ikanalyzer: [smart, max_word]" + - "}.", - disallowEmpty(), - "smart" - ); - public static final ConfigOption COMPUTER_CONFIG = - new ConfigOption<>( - "computer.config", - "The config file path of computer job.", - disallowEmpty(), - "./conf/computer.yaml" - ); - public static final ConfigOption K8S_OPERATOR_TEMPLATE = - new ConfigOption<>( - "k8s.operator_template", - "the path of operator container template.", - disallowEmpty(), - "./conf/operator-template.yaml" - ); - public static final ConfigOption K8S_QUOTA_TEMPLATE = - new ConfigOption<>( - "k8s.quota_template", - "the path of resource quota template.", - disallowEmpty(), - "./conf/resource-quota-template.yaml" - ); - public static final ConfigOption OLTP_CONCURRENT_THREADS = - new ConfigOption<>( - "oltp.concurrent_threads", - "Thread number to concurrently execute oltp algorithm.", - rangeInt(0, 65535), - 10 - ); - public static final ConfigOption OLTP_CONCURRENT_DEPTH = - new ConfigOption<>( - "oltp.concurrent_depth", - "The min depth to enable concurrent oltp algorithm.", - rangeInt(0, 65535), - 10 - ); - public static final ConfigConvOption OLTP_COLLECTION_TYPE = - new ConfigConvOption<>( - "oltp.collection_type", - "The implementation type of collections " + - "used in oltp algorithm.", - allowValues("JCF", "EC", "FU"), - CollectionType::valueOf, - "EC" - ); - public static final ConfigOption PD_PEERS = new ConfigOption<>( - "pd.peers", - "The addresses of pd nodes, separated with commas.", - disallowEmpty(), - "127.0.0.1:8686" - ); - public static final ConfigOption MEMORY_MODE = new ConfigOption<>( - "memory.mode", - "The memory mode used for query in HugeGraph.", - disallowEmpty(), - "off-heap" - ); - public static final ConfigOption MAX_MEMORY_CAPACITY = new ConfigOption<>( - "memory.max_capacity", - "The maximum memory capacity that can be managed for all queries in HugeGraph.", - nonNegativeInt(), - Bytes.GB - ); - public static final ConfigOption ONE_QUERY_MAX_MEMORY_CAPACITY = new ConfigOption<>( - "memory.one_query_max_capacity", - "The maximum memory capacity that can be managed for a query in HugeGraph.", - nonNegativeInt(), - Bytes.MB * 100 - ); - public static final ConfigOption MEMORY_ALIGNMENT = new ConfigOption<>( - "memory.alignment", - "The alignment used for round memory size.", - nonNegativeInt(), - 8L - ); - public static final ConfigOption GRAPH_SPACE = - new ConfigOption<>( - "graphspace", - "The graph space name.", - null, - "DEFAULT" - ); - private static volatile CoreOptions instance; - - private CoreOptions() { - super(); - } - - public static synchronized CoreOptions instance() { - if (instance == null) { - instance = new CoreOptions(); - // Should initialize all static members first, then register. - instance.registerOptions(); - } - return instance; - } -} diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Aggregate.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Aggregate.java index 38f1365f67..51d2ee9db4 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Aggregate.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Aggregate.java @@ -20,19 +20,21 @@ package org.apache.hugegraph.query; import java.util.Iterator; +import java.util.function.BiFunction; + +import org.apache.tinkerpop.gremlin.util.NumberHelper; -@Deprecated public class Aggregate

{ private final AggregateFuncDefine

func; private final String column; - public Aggregate(AggregateFuncDefine func, String column) { + public Aggregate(AggregateFuncDefine

func, String column) { this.func = func; this.column = column; } - public AggregateFuncDefine func() { + public AggregateFuncDefine

func() { return this.func; } @@ -58,4 +60,58 @@ public String toString() { this.column == null ? "*" : this.column); } + public enum AggregateFunc implements AggregateFuncDefine { + + COUNT("count", 0L, NumberHelper::add), + MAX("max", -Double.MAX_VALUE, NumberHelper::max), + MIN("min", Double.MAX_VALUE, NumberHelper::min), + AVG("avg", 0D, NumberHelper::add), + SUM("sum", 0L, NumberHelper::add); + + private final String name; + private final Number defaultValue; + private final BiFunction merger; + + AggregateFunc(String name, Number defaultValue, + BiFunction merger) { + this.name = name; + this.defaultValue = defaultValue; + this.merger = merger; + } + + @Override + public String string() { + return this.name; + } + + @Override + public boolean countAll() { + return this == COUNT; + } + + @Override + public Number defaultValue() { + return this.defaultValue; + } + + @Override + public Number reduce(Iterator results) { + Number number; + long count = 0L; + if (results.hasNext()) { + number = results.next(); + count++; + } else { + return this.defaultValue; + } + while (results.hasNext()) { + number = this.merger.apply(number, results.next()); + count++; + } + if (this == AVG) { + number = NumberHelper.div(number, count); + } + return number; + } + } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/AggregateFuncDefine.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/AggregateFuncDefine.java index d883aab49c..7cd74118c6 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/AggregateFuncDefine.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/AggregateFuncDefine.java @@ -26,7 +26,8 @@ * * @param

*/ -public interface AggregateFuncDefine

{ +public interface AggregateFuncDefine

{ + String string(); P defaultValue(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/BatchConditionQuery.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/BatchConditionQuery.java similarity index 96% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/BatchConditionQuery.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/query/BatchConditionQuery.java index 181ee48648..32f09e03e3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/BatchConditionQuery.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/BatchConditionQuery.java @@ -15,13 +15,13 @@ * limitations under the License. */ -package org.apache.hugegraph.backend.query; +package org.apache.hugegraph.query; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import org.apache.hugegraph.backend.query.Condition.RelationType; +import org.apache.hugegraph.query.Condition.RelationType; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.E; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Condition.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Condition.java index d1ec7e52fa..c2d63e4f35 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Condition.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Condition.java @@ -17,10 +17,16 @@ package org.apache.hugegraph.query; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.text.similarity.LevenshteinDistance; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.regex.Pattern; + import org.apache.hugegraph.backend.Shard; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.structure.BaseElement; @@ -32,9 +38,10 @@ import org.apache.hugegraph.util.NumericUtil; import org.apache.tinkerpop.gremlin.process.traversal.PBiPredicate; -import java.util.*; -import java.util.function.BiFunction; -import java.util.regex.Pattern; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.text.similarity.LevenshteinDistance; public abstract class Condition { diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/ConditionQuery.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/ConditionQuery.java index 553fec9b8c..44bc00e824 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/ConditionQuery.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/ConditionQuery.java @@ -17,17 +17,26 @@ package org.apache.hugegraph.query; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.id.SplicingIdGenerator; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.query.Condition.Relation; import org.apache.hugegraph.query.Condition.RelationType; +import org.apache.hugegraph.query.serializer.AggregateAdapter; import org.apache.hugegraph.query.serializer.QueryAdapter; import org.apache.hugegraph.query.serializer.QueryIdAdapter; import org.apache.hugegraph.structure.BaseElement; @@ -35,12 +44,18 @@ import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.CollectionType; import org.apache.hugegraph.type.define.HugeKeys; -import org.apache.hugegraph.util.*; +import org.apache.hugegraph.util.CollectionUtil; +import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.InsertionOrderUtil; +import org.apache.hugegraph.util.LongEncoding; +import org.apache.hugegraph.util.NumericUtil; import org.apache.hugegraph.util.collection.CollectionFactory; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.util.*; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; public class ConditionQuery extends IdQuery { @@ -57,9 +72,9 @@ public class ConditionQuery extends IdQuery { private static final Gson gson = new GsonBuilder() .registerTypeAdapter(Condition.class, new QueryAdapter()) .registerTypeAdapter(Id.class, new QueryIdAdapter()) + .registerTypeAdapter(Aggregate.class, new AggregateAdapter()) .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") .create(); - private static final int indexStringValueLength = 20; static { List list = new ArrayList<>(INDEX_SYM_MAX - INDEX_SYM_MIN); @@ -91,91 +106,6 @@ public ConditionQuery(HugeType resultType, Query originQuery) { super(resultType, originQuery); } - /** - * Index and composite index interception - * - * @param values - * @return - */ - public static String concatValuesLimitLength(List values) { - List newValues = new ArrayList<>(values.size()); - for (Object v : values) { - v = convertLargeValue(v); - newValues.add(convertNumberIfNeeded(v)); - } - return SplicingIdGenerator.concatValues(newValues); - } - - /** - * Index and composite index interception - * - * @param value - * @return - */ - public static String concatValuesLimitLength(Object value) { - if (value instanceof List) { - return concatValuesLimitLength((List) value); - } - - if (needConvertNumber(value)) { - return LongEncoding.encodeNumber(value); - } - value = convertLargeValue(value); - return value.toString(); - } - - public static int getIndexStringValueLength() { - return indexStringValueLength; - } - - /** - * Extract the String value - * - * @param v - * @return - */ - private static Object convertLargeValue(Object v) { - - if (Objects.nonNull(v) && v instanceof String && - ((String) v).length() > getIndexStringValueLength()) { - - v = ((String) v).substring(0, getIndexStringValueLength()); - - } - - return v; - } - - private static Object convertNumberIfNeeded(Object value) { - if (needConvertNumber(value)) { - return LongEncoding.encodeNumber(value); - } - return value; - } - - private static boolean removeValue(Set values, Object value) { - for (Object compareValue : values) { - if (numberEquals(compareValue, value)) { - values.remove(compareValue); - return true; - } - } - return false; - } - - private static boolean numberEquals(Object number1, Object number2) { - // Same class compare directly - if (number1.getClass().equals(number2.getClass())) { - return number1.equals(number2); - } - // Otherwise convert to BigDecimal to make two numbers comparable - Number n1 = NumericUtil.convertToNumber(number1); - Number n2 = NumericUtil.convertToNumber(number2); - BigDecimal b1 = BigDecimal.valueOf(n1.doubleValue()); - BigDecimal b2 = BigDecimal.valueOf(n2.doubleValue()); - return b1.compareTo(b2) == 0; - } - public static String concatValues(List values) { assert !values.isEmpty(); List newValues = new ArrayList<>(values.size()); @@ -199,15 +129,8 @@ public static String concatValues(Object value) { } public static ConditionQuery fromBytes(byte[] bytes) { - Gson gson = new GsonBuilder() - .registerTypeAdapter(Condition.class, new QueryAdapter()) - .registerTypeAdapter(Id.class, new QueryIdAdapter()) - .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") - .create(); - String cqs = new String(bytes, StandardCharsets.UTF_8); - ConditionQuery conditionQuery = gson.fromJson(cqs, ConditionQuery.class); - - return conditionQuery; + return gson.fromJson(new String(bytes, StandardCharsets.UTF_8), + ConditionQuery.class); } private static boolean needConvertNumber(Object value) { @@ -256,11 +179,7 @@ public boolean shard() { return this.shard; } - private void ensureElement2IndexValueMap() { - if (this.element2IndexValueMap == null) { - this.element2IndexValueMap = new Element2IndexValueMap(); - } - } + public ConditionQuery query(Condition condition) { // Query by id (HugeGraph-259) @@ -345,12 +264,10 @@ public void resetConditions() { } public void recordIndexValue(Id propertyId, Id id, Object indexValue) { - this.ensureElement2IndexValueMap(); this.element2IndexValueMap().addIndexValue(propertyId, id, indexValue); } public void selectedIndexField(Id indexField) { - this.ensureElement2IndexValueMap(); this.element2IndexValueMap().selectedIndexField(indexField); } @@ -491,24 +408,27 @@ public T condition(Object key) { return value; } + boolean initialized = false; Set intersectValues = InsertionOrderUtil.newSet(); for (Object value : valuesEQ) { List valueAsList = ImmutableList.of(value); - if (intersectValues.isEmpty()) { + if (!initialized) { intersectValues.addAll(valueAsList); + initialized = true; } else { CollectionUtil.intersectWithModify(intersectValues, - valueAsList); + valueAsList); } } for (Object value : valuesIN) { @SuppressWarnings("unchecked") List valueAsList = (List) value; - if (intersectValues.isEmpty()) { + if (!initialized) { intersectValues.addAll(valueAsList); + initialized = true; } else { CollectionUtil.intersectWithModify(intersectValues, - valueAsList); + valueAsList); } } @@ -516,8 +436,8 @@ public T condition(Object key) { return null; } E.checkState(intersectValues.size() == 1, - "Illegal key '%s' with more than one value: %s", - key, intersectValues); + "Illegal key '%s' with more than one value: %s", + key, intersectValues); @SuppressWarnings("unchecked") T value = (T) intersectValues.iterator().next(); return value; @@ -705,30 +625,7 @@ public String userpropValuesString(List fields) { return concatValues(values); } - public String userpropValuesStringForIndex(List fields) { - List values = new ArrayList<>(fields.size()); - for (Id field : fields) { - boolean got = false; - for (Relation r : this.userpropRelations()) { - if (r.key().equals(field) && !r.isSysprop()) { - E.checkState(r.relation() == RelationType.EQ || - r.relation() == RelationType.CONTAINS, - "Method userpropValues(List) only " + - "used for secondary index, " + - "relation must be EQ or CONTAINS, but got %s", - r.relation()); - values.add(r.serialValue()); - got = true; - } - } - if (!got) { - throw new BackendException( - "No such userprop named '%s' in the query '%s'", - field, this); - } - } - return concatValuesLimitLength(values); - } + public Set userpropValues(Id field) { Set values = new HashSet<>(); @@ -856,6 +753,10 @@ public Condition.Relation copyRelationAndUpdateQuery(Object key) { @Override public boolean test(BaseElement element) { + return this.test(element, this.resultsFilter); + } + + public boolean test(BaseElement element, ResultsFilter filter) { if (!this.ids().isEmpty() && !super.test(element)) { return false; } @@ -867,19 +768,25 @@ public boolean test(BaseElement element) { * We can't use sub-query results-filter here for fresh element which is * not committed to backend store, because it's not from a sub-query. */ - if (this.resultsFilter != null && !element.fresh()) { - return this.resultsFilter.test(element); + if (filter != null && !element.fresh()) { + return filter.test(element); } /* * NOTE: seems need to keep call checkRangeIndex() for each condition, * so don't break early even if test() return false. - */ + */ boolean valid = true; + Map rangeIndexMatches = null; + if (this.element2IndexValueMap != null) { + rangeIndexMatches = new HashMap<>(); + } for (Condition cond : this.conditions) { valid &= cond.test(element); - valid &= this.element2IndexValueMap == null || - this.element2IndexValueMap.checkRangeIndex(element, cond); + if (this.element2IndexValueMap != null) { + valid &= this.element2IndexValueMap.checkRangeIndex( + element, cond, rangeIndexMatches); + } } return valid; } @@ -944,6 +851,10 @@ public void registerResultsFilter(ResultsFilter filter) { this.resultsFilter = filter; } + public ResultsFilter resultsFilter() { + return this.resultsFilter; + } + public void updateResultsFilter() { Query originQuery = this.originQuery(); if (originQuery instanceof ConditionQuery) { @@ -1017,15 +928,7 @@ private static boolean removeFieldValue(Set values, return false; } - private static boolean removeValue(Set values, Object value) { - for (Object compareValue : values) { - if (numberEquals(compareValue, value)) { - values.remove(compareValue); - return true; - } - } - return false; - } + private static boolean numberEquals(Object number1, Object number2) { // Same class compare directly @@ -1068,10 +971,7 @@ public Set toRemoveIndexValues(Id indexField, Id elementId) { } public Set removeIndexValues(Id indexField, Id elementId) { - if (!this.filed2IndexValues.containsKey(indexField)) { - return null; - } - return this.filed2IndexValues.get(indexField).get(elementId); + return this.toRemoveIndexValues(indexField, elementId); } public void addLeftIndex(Id elementId, Id indexField, @@ -1090,12 +990,7 @@ public Set getLeftIndex(Id elementId) { public void addLeftIndex(Id indexField, Set indexValues, Id elementId) { - LeftIndex leftIndex = new LeftIndex(indexValues, indexField); - if (this.leftIndexMap.containsKey(elementId)) { - this.leftIndexMap.get(elementId).add(leftIndex); - } else { - this.leftIndexMap.put(elementId, Sets.newHashSet(leftIndex)); - } + this.addLeftIndex(elementId, indexField, indexValues); } public void removeElementLeftIndex(Id elementId) { @@ -1103,25 +998,36 @@ public void removeElementLeftIndex(Id elementId) { } public boolean checkRangeIndex(BaseElement element, Condition cond) { + return this.checkRangeIndex(element, cond, new HashMap<>()); + } + + public boolean checkRangeIndex(BaseElement element, Condition cond, + Map rangeIndexMatches) { // Not UserpropRelation if (!(cond instanceof Condition.UserpropRelation)) { return true; } - Condition.UserpropRelation propRelation = (Condition.UserpropRelation) cond; + Condition.UserpropRelation propRelation = + (Condition.UserpropRelation) cond; Id propId = propRelation.key(); Set fieldValues = this.toRemoveIndexValues(propId, - element.id()); + element.id()); if (fieldValues == null) { // Not range index return true; } + if (rangeIndexMatches.containsKey(propId)) { + return rangeIndexMatches.get(propId); + } + BaseProperty property = element.getProperty(propId); if (property == null) { // Property value has been deleted, so it's not matched this.addLeftIndex(element.id(), propId, fieldValues); - return false; + return this.cacheRangeIndexMatch(rangeIndexMatches, propId, + false); } /* @@ -1130,7 +1036,7 @@ public boolean checkRangeIndex(BaseElement element, Condition cond) { * wait the left-index to be removed. */ boolean hasRightValue = removeFieldValue(fieldValues, - property.value()); + property.value()); if (!fieldValues.isEmpty()) { this.addLeftIndex(element.id(), propId, fieldValues); } @@ -1142,55 +1048,23 @@ public boolean checkRangeIndex(BaseElement element, Condition cond) { * the element is valid or not. */ if (this.selectedIndexField != null) { - return !propId.equals(this.selectedIndexField) || hasRightValue; + hasRightValue = !propId.equals(this.selectedIndexField) || + hasRightValue; } - return hasRightValue; + return this.cacheRangeIndexMatch(rangeIndexMatches, propId, + hasRightValue); } - public boolean validRangeIndex(BaseElement element, Condition cond) { - // Not UserpropRelation - if (!(cond instanceof Condition.UserpropRelation)) { - return true; - } - - Condition.UserpropRelation propRelation = (Condition.UserpropRelation) cond; - Id propId = propRelation.key(); - Set fieldValues = this.removeIndexValues(propId, - element.id()); - if (fieldValues == null) { - // Not range index - return true; - } - - BaseProperty hugeProperty = element.getProperty(propId); - if (hugeProperty == null) { - // Property value has been deleted - this.addLeftIndex(propId, fieldValues, element.id()); - return false; - } - - /* - * NOTE: If success remove means has correct index, - * we should add left index values to left index map - * waiting to be removed - */ - boolean hasRightValue = removeValue(fieldValues, hugeProperty.value()); - if (fieldValues.size() > 0) { - this.addLeftIndex(propId, fieldValues, element.id()); - } - - /* - * NOTE: When query by more than one range index field, - * if current field is not the selected one, it can only be used to - * determine whether the index values matched, can't determine - * the element is valid or not - */ - if (this.selectedIndexField != null) { - return !propId.equals(this.selectedIndexField) || hasRightValue; - } + private boolean cacheRangeIndexMatch(Map rangeIndexMatches, + Id propertyId, + boolean matched) { + rangeIndexMatches.put(propertyId, matched); + return matched; + } - return hasRightValue; + public boolean validRangeIndex(BaseElement element, Condition cond) { + return this.checkRangeIndex(element, cond, new HashMap<>()); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdPrefixQuery.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdPrefixQuery.java similarity index 94% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdPrefixQuery.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdPrefixQuery.java index c14a07070d..933d1ea9f2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdPrefixQuery.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdPrefixQuery.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.hugegraph.backend.query; +package org.apache.hugegraph.query; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.structure.BaseElement; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; @@ -76,7 +76,7 @@ public boolean empty() { } @Override - public boolean test(HugeElement element) { + public boolean test(BaseElement element) { byte[] elem = element.id().asBytes(); int cmp = Bytes.compare(elem, this.start.asBytes()); boolean matchedStart = this.inclusiveStart ? cmp >= 0 : cmp > 0; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdQuery.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdQuery.java index 1235dfebc0..b07359af4e 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdQuery.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdQuery.java @@ -29,6 +29,7 @@ import org.apache.hugegraph.util.InsertionOrderUtil; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; public class IdQuery extends Query { @@ -124,4 +125,67 @@ public IdQuery copy() { InsertionOrderUtil.newList(this.ids); return query; } + + public static final class OneIdQuery extends IdQuery { + + private Id id; + + public OneIdQuery(HugeType resultType, Id id) { + super(resultType); + super.mustSortByInput = false; + this.id = id; + } + + public OneIdQuery(Query originQuery, Id id) { + super(originQuery.resultType(), originQuery); + super.mustSortByInput = false; + this.id = id; + } + + public Id id() { + return this.id; + } + + public void resetId(Id id) { + this.id = id; + } + + @Override + public int idsSize() { + return this.id == null ? 0 : 1; + } + + @Override + public Set ids() { + return this.id == null ? ImmutableSet.of() : + ImmutableSet.of(this.id); + } + + @Override + public void resetIds() { + this.id = null; + } + + @Override + public IdQuery query(Id id) { + E.checkArgumentNotNull(id, "Query id can't be null"); + this.id = id; + return this; + } + + @Override + public boolean test(BaseElement element) { + if (this.id == null) { + return true; + } + return this.id.equals(element.id()); + } + + @Override + public IdQuery copy() { + OneIdQuery query = (OneIdQuery) super.copy(); + assert this.id.equals(query.id); + return query; + } + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdRangeQuery.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdRangeQuery.java similarity index 94% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdRangeQuery.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdRangeQuery.java index 781dc72d08..d276d8bc54 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/IdRangeQuery.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/IdRangeQuery.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.hugegraph.backend.query; +package org.apache.hugegraph.query; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.structure.BaseElement; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; @@ -82,7 +82,7 @@ public boolean empty() { } @Override - public boolean test(HugeElement element) { + public boolean test(BaseElement element) { int cmp1 = Bytes.compare(element.id().asBytes(), this.start.asBytes()); int cmp2 = Bytes.compare(element.id().asBytes(), this.end.asBytes()); return (this.inclusiveStart ? cmp1 >= 0 : cmp1 > 0) && diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Query.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Query.java index 2151cd6d0b..3cf97d4a14 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Query.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/Query.java @@ -81,8 +81,7 @@ public class Query implements Cloneable { private List selects = InsertionOrderUtil.newList(); - @Deprecated - private transient Aggregate aggregate; + private Aggregate aggregate; private Query originQuery; @@ -97,10 +96,6 @@ public Query() { } - private static final ThreadLocal capacityContext = new ThreadLocal<>(); - - private static int indexStringValueLength = 20; - public Query(HugeType resultType) { this(resultType, null); } @@ -271,12 +266,12 @@ public Set skipOffsetIfNeeded(Set elems) { if (fromIndex < 0L) { // Skipping offset is overhead, no need to skip fromIndex = 0L; - } else if (fromIndex > 0L) { + } + // An index holder yields ids in batches, only count this batch's ids + fromIndex = Math.min(fromIndex, elems.size()); + if (fromIndex > 0L) { this.goOffset(fromIndex); } - E.checkArgument(fromIndex <= Integer.MAX_VALUE, - "Offset must be <= 0x7fffffff, but got '%s'", - fromIndex); if (fromIndex >= elems.size()) { return ImmutableSet.of(); @@ -447,21 +442,21 @@ public void checkCapacity(long count) throws LimitExceedException { } } - public Aggregate aggregate() { + public Aggregate aggregate() { return this.aggregate; } - public Aggregate aggregateNotNull() { + public Aggregate aggregateNotNull() { E.checkArgument(this.aggregate != null, "The aggregate must be set for number query"); return this.aggregate; } - public void aggregate(AggregateFuncDefine func, String property) { - this.aggregate = new Aggregate(func, property); + public void aggregate(AggregateFuncDefine func, String property) { + this.aggregate = new Aggregate<>(func, property); } - public void aggregate(Aggregate aggregate) { + public void aggregate(Aggregate aggregate) { this.aggregate = aggregate; } @@ -569,7 +564,6 @@ public int hashCode() { Objects.hashCode(this.page) ^ this.ids().hashCode() ^ this.conditions().hashCode() ^ - this.selects().hashCode() ^ Boolean.hashCode(this.withProperties); if (this.resultType == null) { return hash; @@ -665,16 +659,9 @@ public boolean isTaskQuery() { return false; } - public static int getIndexStringValueLength() { - return indexStringValueLength; - } - public static void setIndexStringValueLength(int indexStringValueLengthTmp) { - if (indexStringValueLengthTmp <= 1) { - indexStringValueLengthTmp = 20; - } - indexStringValueLength = indexStringValueLengthTmp; - } + + public void select(Id id) { if (!this.selects.contains(id)) { diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/AggregateAdapter.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/AggregateAdapter.java new file mode 100644 index 0000000000..c2fd2196a0 --- /dev/null +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/AggregateAdapter.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package org.apache.hugegraph.query.serializer; + +import java.lang.reflect.Type; +import java.util.Locale; + +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** Preserves the original query aggregate descriptor without Java class names. */ +public final class AggregateAdapter implements JsonSerializer>, + JsonDeserializer> { + + @Override + public JsonElement serialize(Aggregate aggregate, Type type, + JsonSerializationContext context) { + JsonObject result = new JsonObject(); + // Both the shared enum and external strategies expose their function name. + // Only names supported by the original query protocol may cross the wire. + AggregateFunc func = function(aggregate.func().string().toUpperCase(Locale.ROOT)); + result.addProperty("func", func.name()); + if (aggregate.column() != null) { + result.addProperty("column", aggregate.column()); + } + return result; + } + + @Override + public Aggregate deserialize(JsonElement json, Type type, + JsonDeserializationContext context) { + JsonObject aggregate = json.getAsJsonObject(); + AggregateFunc func = function(aggregate.get("func").getAsString()); + JsonElement column = aggregate.get("column"); + return new Aggregate<>(func, column == null || column.isJsonNull() ? null : + column.getAsString()); + } + + private static AggregateFunc function(String name) { + try { + return AggregateFunc.valueOf(name); + } catch (IllegalArgumentException e) { + throw new JsonParseException("Unsupported aggregate function: " + name, e); + } + } +} diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/QueryAdapter.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/QueryAdapter.java index e9975f57cd..b7b7c40c5b 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/QueryAdapter.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/QueryAdapter.java @@ -25,6 +25,7 @@ import org.apache.hugegraph.query.Condition; import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.util.LegacyClassNames; import com.google.common.collect.ImmutableMap; import com.google.gson.JsonDeserializationContext; @@ -35,6 +36,7 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.reflect.TypeToken; +// TODO(hugegraph/hugegraph#259): use stable value type tags while retaining legacy query decoding. public class QueryAdapter extends AbstractSerializerAdapter { static ImmutableMap cls = @@ -55,6 +57,13 @@ static boolean isPrimitive(Class clz) { } } + // Old server queries include Java class names in relation values. + // Resolve only the migrated names here; no legacy implementation is needed. + private static Class valueClass(String name) throws ClassNotFoundException { + Class mapped = LegacyClassNames.lookup(name); + return mapped != null ? mapped : Class.forName(name); + } + @Override public Map validType() { return cls; @@ -72,7 +81,7 @@ public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserialization if (valueElement.isJsonObject()) { String cls = valueElement.getAsJsonObject().get("cls").getAsString(); try { - Class actualClass = Class.forName(cls); + Class actualClass = valueClass(cls); Object obj = context.deserialize(valueElement, actualClass); ((Condition.Relation) condition).value(obj); } catch (ClassNotFoundException e) { @@ -82,7 +91,7 @@ public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserialization if (valueElement.isJsonArray()) { String cls = elElement.getAsJsonObject().get("valuecls").getAsString(); try { - Class actualClass = Class.forName(cls); + Class actualClass = valueClass(cls); Type type = TypeToken.getParameterized(ArrayList.class, actualClass) .getType(); Object value = context.deserialize(valueElement, type); @@ -93,7 +102,7 @@ public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserialization } else { String cls = elElement.getAsJsonObject().get("valuecls").getAsString(); try { - Class actualClass = Class.forName(cls); + Class actualClass = valueClass(cls); Object obj = context.deserialize(valueElement, actualClass); ((Condition.Relation) condition).value(obj); } catch (ClassNotFoundException e) { diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BinaryElementSerializer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BinaryElementSerializer.java index 03229b42f7..82f2f8952e 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BinaryElementSerializer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BinaryElementSerializer.java @@ -24,18 +24,19 @@ import java.util.Arrays; import java.util.Base64; import java.util.Collection; -import java.util.Map; +import java.util.function.BiConsumer; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.NotImplementedException; import org.apache.hugegraph.HugeGraphSupplier; import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.backend.BinaryId; -import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.id.EdgeId; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.id.IdGenerator; import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.struct.schema.SchemaElement; import org.apache.hugegraph.struct.schema.VertexLabel; @@ -43,10 +44,14 @@ import org.apache.hugegraph.structure.BaseElement; import org.apache.hugegraph.structure.BaseProperty; import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.BaseVertex.TypeContext; import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.serializer.BytesBuffer.IndexColumnName; +import org.apache.hugegraph.serializer.BytesBuffer.IndexExpiryLayout; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; import org.apache.hugegraph.type.define.EdgeLabelType; +import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; @@ -107,32 +112,46 @@ public static Id ownerId(Index index) { protected void parseProperty(HugeGraphSupplier graph, Id pkeyId, - BytesBuffer buffer, - BaseElement owner) { - PropertyKey pkey = graph != null ? - graph.propertyKey(pkeyId) : - new PropertyKey(graph, pkeyId, ""); - // Parse value - Object value = buffer.readProperty(pkey); - // Set properties of vertex/edge - if (pkey.cardinality() == Cardinality.SINGLE) { - owner.addProperty(pkey, value); - } else { - if (!(value instanceof Collection)) { - throw new HugeException( - "Invalid value of non-single property: %s", value); - } - owner.addProperty(pkey, value); + BytesBuffer buffer, BaseElement owner) { + this.parseProperty(graph, pkeyId, buffer, true, owner::addProperty); + } + + public void parseSchemaProperty(HugeGraphSupplier graph, Id pkeyId, + BytesBuffer buffer, + BiConsumer propertySink) { + E.checkArgumentNotNull(graph, "Schema property decoding requires a schema supplier"); + this.parseProperty(graph, pkeyId, buffer, false, propertySink); + } + + private void parseProperty(HugeGraphSupplier graph, Id pkeyId, + BytesBuffer buffer, boolean tagged, + BiConsumer propertySink) { + PropertyKey pkey = graph != null ? graph.propertyKey(pkeyId) : + new PropertyKey(null, pkeyId, ""); + Object value = tagged ? buffer.readProperty(pkey) : buffer.readSchemaProperty(pkey); + if (pkey.cardinality() != Cardinality.SINGLE && !(value instanceof Collection)) { + throw new BackendException("Invalid value of non-single property: %s", value); } + propertySink.accept(pkey, value); } public void parseProperties(HugeGraphSupplier graph, BytesBuffer buffer, BaseElement owner) { + this.parseProperties(graph, buffer, true, owner::addProperty); + } + + public void parseSchemaProperties(HugeGraphSupplier graph, BytesBuffer buffer, + BiConsumer propertySink) { + E.checkArgumentNotNull(graph, "Schema property decoding requires a schema supplier"); + this.parseProperties(graph, buffer, false, propertySink); + } + + private void parseProperties(HugeGraphSupplier graph, BytesBuffer buffer, + boolean tagged, BiConsumer propertySink) { int size = buffer.readVInt(); assert size >= 0; for (int i = 0; i < size; i++) { - Id pkeyId = IdGenerator.of(buffer.readVInt()); - this.parseProperty(graph, pkeyId, buffer, owner); + this.parsePropertyRecord(graph, buffer, tagged, propertySink); } } @@ -145,74 +164,131 @@ public void parseProperties(HugeGraphSupplier graph, BytesBuffer buffer, */ public BaseVertex parseVertex(HugeGraphSupplier graph, BackendColumn vertexCol, BaseVertex vertex) { + return this.parseVertex(graph, vertexCol, vertex, true, TypeContext.STORAGE); + } + + /** Decode a persisted Server row using schema-supplied property metadata. */ + public BaseVertex parseSchemaVertex(HugeGraphSupplier graph, BackendColumn vertexCol, + BaseVertex vertex) { + return this.parseSchemaVertex(graph, vertexCol, vertex, TypeContext.STORAGE); + } + + public BaseVertex parseSchemaVertex(HugeGraphSupplier graph, BackendColumn vertexCol, + BaseVertex vertex, TypeContext typeContext) { + E.checkArgumentNotNull(graph, "Schema vertex decoding requires a schema supplier"); + return this.parseVertex(graph, vertexCol, vertex, false, typeContext); + } + + private BaseVertex parseVertex(HugeGraphSupplier graph, BackendColumn vertexCol, + BaseVertex vertex, boolean tagged, TypeContext typeContext) { if (vertex == null) { BinaryId binaryId = BytesBuffer.wrap(vertexCol.name).parseId(HugeType.VERTEX); - vertex = new BaseVertex(binaryId.origin(), VertexLabel.NONE); + vertex = new BaseVertex(binaryId.origin(), VertexLabel.NONE, typeContext); } if (ArrayUtils.isEmpty(vertexCol.value)) { // No need to parse vertex properties return vertex; } - BytesBuffer buffer = BytesBuffer.wrap(vertexCol.value); - Id labelId = buffer.readId(); - // Parse vertex label - if (graph != null) { - VertexLabel label = graph.vertexLabelOrNone(labelId); - vertex.correctVertexLabel(label); - } else { - VertexLabel label = new VertexLabel(null, labelId, UNDEF); - vertex.correctVertexLabel(label); - } - // Parse properties - this.parseProperties(graph, buffer, vertex); - - // Parse vertex expired time if needed - if (buffer.remaining() > 0 /*edge.hasTtl()*/) { - this.parseExpiredTime(buffer, vertex); - } + this.parseVertexValue(graph, vertexCol.value, vertex, tagged, vertex::addProperty); return vertex; } + public void parseSchemaVertexValue(HugeGraphSupplier graph, byte[] value, + BaseVertex vertex, + BiConsumer propertySink) { + E.checkArgumentNotNull(graph, "Schema vertex decoding requires a schema supplier"); + this.parseVertexValue(graph, value, vertex, false, propertySink); + } + + private void parseVertexValue(HugeGraphSupplier graph, byte[] value, BaseVertex vertex, + boolean tagged, BiConsumer propertySink) { + BytesBuffer buffer = BytesBuffer.wrap(value); + Id labelId = buffer.readId(); + VertexLabel label = graph != null ? graph.vertexLabelOrNone(labelId) : + new VertexLabel(null, labelId, UNDEF); + vertex.correctVertexLabel(label); + this.parseElementValue(graph, buffer, vertex, tagged, propertySink); + } + /** * Reverse sequence the vertex kv data into vertices of type BaseVertex * * @param olapVertexCol It must be a column of vertex data - * @param vertex When vertex==null, it is used for operator sinking to reverse sequence the col data into olapBaseVertex. - * vertex! When =null, add the col information to olapBaseVertex + * @param vertex The destination vertex; null creates one from the OLAP key. */ public BaseVertex parseVertexOlap(HugeGraphSupplier graph, BackendColumn olapVertexCol, BaseVertex vertex) { + return this.parseVertexOlap(graph, olapVertexCol, vertex, true, TypeContext.STORAGE); + } + + public BaseVertex parseSchemaVertexOlap(HugeGraphSupplier graph, + BackendColumn olapVertexCol, BaseVertex vertex) { + return this.parseSchemaVertexOlap(graph, olapVertexCol, vertex, TypeContext.STORAGE); + } + + public BaseVertex parseSchemaVertexOlap(HugeGraphSupplier graph, + BackendColumn olapVertexCol, BaseVertex vertex, + TypeContext typeContext) { + E.checkArgumentNotNull(graph, "Schema OLAP decoding requires a schema supplier"); + return this.parseVertexOlap(graph, olapVertexCol, vertex, false, typeContext); + } + + private BaseVertex parseVertexOlap(HugeGraphSupplier graph, BackendColumn olapVertexCol, + BaseVertex vertex, boolean tagged, TypeContext typeContext) { if (vertex == null) { BytesBuffer idBuffer = BytesBuffer.wrap(olapVertexCol.name); - // read olap property id - idBuffer.readId(); - // read vertex id which olap property belongs to + // Transient Store OLAP keys include the property ID; Server's + // persisted OLAP column name contains only the vertex ID. + if (tagged) { + idBuffer.readId(); + } Id vertexId = idBuffer.readId(); - vertex = new BaseVertex(vertexId, VertexLabel.NONE); + vertex = new BaseVertex(vertexId, VertexLabel.NONE, typeContext); } - BytesBuffer buffer = BytesBuffer.wrap(olapVertexCol.value); - Id pkeyId = IdGenerator.of(buffer.readVInt()); - this.parseProperty(graph, pkeyId, buffer, vertex); + this.parsePropertyRecord(graph, BytesBuffer.wrap(olapVertexCol.value), + tagged, vertex::addProperty); return vertex; } + public void parseSchemaPropertyRecord(HugeGraphSupplier graph, BytesBuffer buffer, + BiConsumer propertySink) { + E.checkArgumentNotNull(graph, "Schema property decoding requires a schema supplier"); + this.parsePropertyRecord(graph, buffer, false, propertySink); + } + + private void parsePropertyRecord(HugeGraphSupplier graph, BytesBuffer buffer, + boolean tagged, BiConsumer propertySink) { + Id pkeyId = IdGenerator.of(buffer.readVInt()); + this.parseProperty(graph, pkeyId, buffer, tagged, propertySink); + } + /** - * @param cols Deserializing a complete vertex may require multiple cols - * The first col represents the common vertex information in the g+v table, and each subsequent col represents the olap vertices stored in the olap table + * @param cols The first column contains vertex data; subsequent columns contain OLAP properties. */ public BaseVertex parseVertexFromCols(HugeGraphSupplier graph, BackendColumn... cols) { + return this.parseVertexFromCols(graph, true, cols); + } + + public BaseVertex parseSchemaVertexFromCols(HugeGraphSupplier graph, + BackendColumn... cols) { + E.checkArgumentNotNull(graph, "Schema vertex decoding requires a schema supplier"); + return this.parseVertexFromCols(graph, false, cols); + } + + private BaseVertex parseVertexFromCols(HugeGraphSupplier graph, boolean tagged, + BackendColumn... cols) { assert cols.length > 0; BaseVertex vertex = null; for (int index = 0; index < cols.length; index++) { BackendColumn col = cols[index]; if (index == 0) { - vertex = this.parseVertex(graph, col, vertex); + vertex = this.parseVertex(graph, col, vertex, tagged, TypeContext.STORAGE); } else { - this.parseVertexOlap(graph, col, vertex); + this.parseVertexOlap(graph, col, vertex, tagged, TypeContext.STORAGE); } } return vertex; @@ -235,48 +311,38 @@ public Id parseLabelFromCol(BackendColumn col, boolean isVertex) { } public BaseEdge parseEdge(HugeGraphSupplier graph, BackendColumn edgeCol, - BaseVertex ownerVertex, - boolean withEdgeProperties) { - // owner-vertex + dir + edge-label.id() + subLabel.id() + - // + sort-values + other-vertex - - BytesBuffer buffer = BytesBuffer.wrap(edgeCol.name); - // Consume owner-vertex id - Id id = buffer.readId(); - if (ownerVertex == null) { - ownerVertex = new BaseVertex(id, VertexLabel.NONE); - } - - E.checkState(buffer.remaining() > 0, "Missing column type"); + BaseVertex ownerVertex, boolean withEdgeProperties) { + return this.parseEdge(graph, edgeCol, ownerVertex, withEdgeProperties, + true, TypeContext.STORAGE); + } - byte type = buffer.read(); - if (type == HugeType.EDGE_IN.code() || - type == HugeType.EDGE_OUT.code()) { - E.checkState(true, - "Invalid column(%s) with unknown type(%s): 0x%s", - id, type & 0xff, Bytes.toHex(edgeCol.name)); - } + public BaseEdge parseSchemaEdge(HugeGraphSupplier graph, BackendColumn edgeCol, + BaseVertex ownerVertex, boolean withEdgeProperties) { + return this.parseSchemaEdge(graph, edgeCol, ownerVertex, withEdgeProperties, + TypeContext.STORAGE); + } - Id labelId = buffer.readId(); - Id subLabelId = buffer.readId(); - String sortValues = buffer.readStringWithEnding(); - Id otherVertexId = buffer.readId(); - boolean direction = EdgeId.isOutDirectionFromCode(type); - BaseEdge edge; - EdgeLabel edgeLabel; - if (graph == null) { /* when calculation sinking */ - edgeLabel = new EdgeLabel(null, subLabelId, UNDEF); - // If not equal here, need to add fatherId for correct operator sinking - if (subLabelId != labelId) { - edgeLabel.edgeLabelType(EdgeLabelType.SUB); - edgeLabel.fatherId(labelId); - } + public BaseEdge parseSchemaEdge(HugeGraphSupplier graph, BackendColumn edgeCol, + BaseVertex ownerVertex, boolean withEdgeProperties, + TypeContext typeContext) { + E.checkArgumentNotNull(graph, "Schema edge decoding requires a schema supplier"); + return this.parseEdge(graph, edgeCol, ownerVertex, withEdgeProperties, + false, typeContext); + } - } else { - edgeLabel = graph.edgeLabelOrNone(subLabelId); + private BaseEdge parseEdge(HugeGraphSupplier graph, BackendColumn edgeCol, + BaseVertex ownerVertex, boolean withEdgeProperties, + boolean tagged, TypeContext typeContext) { + EdgeId id = BytesBuffer.wrap(edgeCol.name).readEdgeId(true, null); + if (ownerVertex == null) { + ownerVertex = new BaseVertex(id.ownerVertexId(), VertexLabel.NONE, typeContext); } + boolean direction = id.direction() == Directions.OUT; + EdgeLabel edgeLabel = this.edgeLabel(graph, id); + BaseEdge edge; edge = BaseEdge.constructEdge(graph, ownerVertex, direction, - edgeLabel, sortValues, otherVertexId); + edgeLabel, id.sortValues(), id.otherVertexId()); + edge.otherVertex().typeContext(typeContext); if (!withEdgeProperties /*&& !edge.hasTtl()*/) { // only skip properties for edge without ttl @@ -289,19 +355,42 @@ public BaseEdge parseEdge(HugeGraphSupplier graph, BackendColumn edgeCol, return edge; } - // Parse edge-id + edge-properties - buffer = BytesBuffer.wrap(edgeCol.value); + this.parseElementValue(graph, BytesBuffer.wrap(edgeCol.value), edge, + tagged, edge::addProperty); + return edge; + } - // Parse edge properties - this.parseProperties(graph, buffer, edge); + public EdgeLabel edgeLabel(HugeGraphSupplier graph, EdgeId id) { + return this.edgeLabel(graph, id, graph); + } - /* Skip TTL parsing process first - * Can't determine if edge has TTL through edge, need to judge by bytebuffer length */ -// // Parse edge expired time if needed - if (buffer.remaining() > 0 /*edge.hasTtl()*/) { - this.parseExpiredTime(buffer, edge); + public EdgeLabel edgeLabel(HugeGraphSupplier lookupGraph, EdgeId id, + HugeGraphSupplier schemaGraph) { + if (lookupGraph != null) { + return lookupGraph.edgeLabelOrNone(id.subLabelId()); + } + EdgeLabel label = new EdgeLabel(schemaGraph, id.subLabelId(), UNDEF); + if (id.subLabelId() != id.edgeLabelId()) { + label.edgeLabelType(EdgeLabelType.SUB); + label.fatherId(id.edgeLabelId()); + } + return label; + } + + public void parseSchemaEdgeValue(HugeGraphSupplier graph, byte[] value, + BaseEdge edge, + BiConsumer propertySink) { + E.checkArgumentNotNull(graph, "Schema edge decoding requires a schema supplier"); + this.parseElementValue(graph, BytesBuffer.wrap(value), edge, false, propertySink); + } + + private void parseElementValue(HugeGraphSupplier graph, BytesBuffer buffer, + BaseElement element, boolean tagged, + BiConsumer propertySink) { + this.parseProperties(graph, buffer, tagged, propertySink); + if (tagged ? buffer.remaining() > 0 : element.hasTtl()) { + this.parseExpiredTime(buffer, element); } - return edge; } /** @@ -310,19 +399,45 @@ public BaseEdge parseEdge(HugeGraphSupplier graph, BackendColumn edgeCol, */ public Index parseIndex(HugeGraphSupplier graph, BackendColumn indexCol, Index index) { - HugeType indexType = parseIndexType(indexCol); + return this.parseIndex(graph, indexCol, index, false); + } + + /** Decode Server index rows, whose optional expiry is in the column name. */ + public Index parseSchemaIndex(HugeGraphSupplier graph, BackendColumn indexCol) { + E.checkArgumentNotNull(graph, "Schema index decoding requires a schema supplier"); + return this.parseIndex(graph, indexCol, null, true); + } - BytesBuffer buffer = BytesBuffer.wrap(indexCol.name); - BinaryId indexId = buffer.readIndexId(indexType); - Id elemId = buffer.readId(); + private Index parseIndex(HugeGraphSupplier graph, BackendColumn indexCol, + Index index, boolean schema) { + HugeType indexType = parseIndexType(indexCol); + IndexColumnName name = BytesBuffer.wrap(indexCol.name).readIndexColumnName( + indexType, true, schema ? IndexExpiryLayout.OPTIONAL : IndexExpiryLayout.NONE); if (index == null) { - index = Index.parseIndexId(graph, indexType, indexId.asBytes()); + index = Index.parseIndexId(graph, indexType, name.indexId().asBytes()); } - long expiredTime = 0L; - - if (indexCol.value.length > 0) { + long expiredTime = name.expiredTime(); + + if (schema) { + boolean hasTtl = !index.indexLabel().system() && + index.indexLabel().baseLabel().ttl() > 0; + Long legacyExpiredTime = null; + if (!name.hasExpiredTime()) { + // Legacy Store writers kept TTL in an exact value envelope. + // Only use it after the index/element name fields end, never + // search arbitrary field-value bytes for a delimiter. + legacyExpiredTime = this.legacyStoreIndexExpiredTime(indexCol.value); + E.checkState(!hasTtl || legacyExpiredTime != null, + "Missing TTL in schema index column"); + expiredTime = legacyExpiredTime == null ? 0L : legacyExpiredTime; + } + if (legacyExpiredTime == null && indexType.isStringIndex() && + !ArrayUtils.isEmpty(indexCol.value)) { + index.fieldValues(StringEncoding.decode(indexCol.value)); + } + } else if (indexCol.value.length > 0) { // Get delimiter address int delimiterIndex = @@ -355,10 +470,33 @@ public Index parseIndex(HugeGraphSupplier graph, BackendColumn indexCol, } } - index.elementIds(elemId, expiredTime); + index.elementIds(name.elementId(), expiredTime); return index; } + /** Decode the existing Store label envelope only at a complete label-index key boundary. */ + public Long storedLabelIndexExpiredTime(HugeType type, boolean atNameEnd, byte[] value) { + return type.isLabelIndex() && atNameEnd ? this.legacyStoreIndexExpiredTime(value) : null; + } + + private Long legacyStoreIndexExpiredTime(byte[] value) { + // A Store TTL writer emits exactly 0x00 + Base64(long), with no fields. + if (value == null || value.length != 13 || value[0] != BytesBuffer.STRING_ENDING_BYTE) { + return null; + } + try { + byte[] expiry = Base64.getDecoder().decode(Arrays.copyOfRange(value, 1, value.length)); + if (expiry.length != Longs.BYTES || + !Arrays.equals(Base64.getEncoder().encode(expiry), + Arrays.copyOfRange(value, 1, value.length))) { + return null; + } + return Longs.fromByteArray(expiry); + } catch (IllegalArgumentException ignored) { + return null; + } + } + public BackendColumn parseIndex(BackendColumn indexCol) { // Self-parsing index throw new NotImplementedException( @@ -373,21 +511,19 @@ public BackendColumn writeVertex(BaseVertex vertex) { BytesBuffer bufferName = BytesBuffer.allocate(vertex.id().length()); bufferName.writeId(vertex.id()); - int propsCount = vertex.getProperties().size(); - BytesBuffer buffer = BytesBuffer.allocate(8 + 16 * propsCount); - - // Write vertex label - buffer.writeId(vertex.schemaLabel().id()); - - // Write all properties of the vertex - this.formatProperties(vertex.getProperties().values(), buffer); + return BackendColumn.of(bufferName.bytes(), this.formatVertexValue(vertex, true)); + } - // Write vertex expired time if needed - if (vertex.hasTtl()) { - this.formatExpiredTime(vertex.expiredTime(), buffer); - } + public byte[] formatSchemaVertexValue(BaseVertex vertex) { + return this.formatVertexValue(vertex, false); + } - return BackendColumn.of(bufferName.bytes(), buffer.bytes()); + private byte[] formatVertexValue(BaseVertex vertex, boolean tagged) { + BytesBuffer buffer = BytesBuffer.allocate(8 + 16 * vertex.sizeOfProperties()); + buffer.writeId(vertex.schemaLabel().id()); + this.formatElementProperties(vertex, buffer, tagged); + this.formatElementExpiredTime(vertex, buffer); + return buffer.bytes(); } public BackendColumn writeOlapVertex(BaseVertex vertex) { @@ -396,18 +532,9 @@ public BackendColumn writeOlapVertex(BaseVertex vertex) { BaseProperty baseProperty = vertex.getProperties().values() .iterator().next(); PropertyKey propertyKey = baseProperty.propertyKey(); - buffer.writeVInt(SchemaElement.schemaId(propertyKey.id())); - buffer.writeProperty(propertyKey.cardinality(), propertyKey.dataType(), - baseProperty.value()); - - // OLAP table merge, key is {property_key_id}{vertex_id} - BytesBuffer bufferName = - BytesBuffer.allocate(1 + propertyKey.id().length() + 1 + - vertex.id().length()); - bufferName.writeId(propertyKey.id()); - bufferName.writeId(vertex.id()).bytes(); + this.formatProperty(baseProperty, buffer, true); - return BackendColumn.of(bufferName.bytes(), buffer.bytes()); + return BackendColumn.of(OlapKey.format(propertyKey.id(), vertex.id()), buffer.bytes()); } public BackendColumn writeEdge(BaseEdge edge) { @@ -424,6 +551,49 @@ public BackendColumn writeIndex(Index index) { formatIndexValue(index)); } + /** Write Store-owned rows with stable keys and the existing storage label-expiry envelope. */ + public BackendColumn writeSchemaIndex(Index index) { + BackendColumn column = this.formatSchemaIndex( + index.type(), index.indexLabelId(), index.fieldValues(), index.elementId(), + true, index.hasTtl(), index.expiredTime()); + if (this.storageLabelHasTtl(index)) { + // Preserve label-index keys so Core append/remove addresses the same row. + column.value = this.formatIndexValue(index); + } + return column; + } + + public BackendColumn formatSchemaIndex(HugeType type, Id indexLabelId, Object fieldValues, + Id elementId, boolean withIdPrefix, + boolean hasTtl, long expiredTime) { + Id rawId = Index.formatIndexId(type, indexLabelId, fieldValues); + boolean hashed = !type.isNumericIndex() && indexIdLengthExceedLimit(rawId); + Id indexId = schemaIndexId(type, indexLabelId, fieldValues); + int capacity = 1 + elementId.length() + (withIdPrefix ? 1 + indexId.length() : 0); + BytesBuffer name = BytesBuffer.allocate(capacity); + if (withIdPrefix) { + name.writeIndexId(indexId, type); + } + name.writeId(elementId); + if (hasTtl) { + name.writeVLong(expiredTime); + } + byte[] value = hashed ? StringEncoding.encode(fieldValues.toString()) : BytesBuffer.BYTES_EMPTY; + return BackendColumn.of(name.bytes(), value); + } + + public static Id schemaIndexId(HugeType type, Id indexLabelId, Object fieldValues) { + Id id = Index.formatIndexId(type, indexLabelId, fieldValues); + if (!type.isNumericIndex() && indexIdLengthExceedLimit(id)) { + id = Index.formatIndexHashId(type, indexLabelId, fieldValues); + } + return id; + } + + public static boolean indexIdLengthExceedLimit(Id id) { + return id.asBytes().length > BytesBuffer.INDEX_HASH_ID_THRESHOLD; + } + private byte[] formatIndexName(Index index) { BytesBuffer buffer; Id elemId = index.elementId(); @@ -444,8 +614,13 @@ private byte[] formatIndexName(Index index) { * @return format * | empty(field-value) | 0x00 | base64(expiredtime) | */ + private boolean storageLabelHasTtl(Index index) { + return (index.indexLabel() == IndexLabel.label(HugeType.VERTEX) || + index.indexLabel() == IndexLabel.label(HugeType.EDGE)) && index.expiredTime() > 0; + } + private byte[] formatIndexValue(Index index) { - if (index.hasTtl()) { + if (this.storageLabelHasTtl(index) || index.hasTtl()) { BytesBuffer valueBuffer = BytesBuffer.allocate(14); valueBuffer.write(BytesBuffer.STRING_ENDING_BYTE); @@ -494,32 +669,64 @@ public byte[] formatEdgeName(BaseEdge edge) { } protected byte[] formatEdgeValue(BaseEdge edge) { - Map> properties = edge.getProperties(); - int propsCount = properties.size(); - BytesBuffer buffer = BytesBuffer.allocate(4 + 16 * propsCount); + return this.formatEdgeValue(edge, true); + } - // Write edge properties - this.formatProperties(properties.values(), buffer); + public byte[] formatSchemaEdgeValue(BaseEdge edge) { + return this.formatEdgeValue(edge, false); + } - // Write edge expired time if needed - if (edge.hasTtl()) { - this.formatExpiredTime(edge.expiredTime(), buffer); + private byte[] formatEdgeValue(BaseEdge edge, boolean tagged) { + BytesBuffer buffer = BytesBuffer.allocate(4 + 16 * edge.sizeOfProperties()); + this.formatElementProperties(edge, buffer, tagged); + this.formatElementExpiredTime(edge, buffer); + return buffer.bytes(); + } + + private void formatElementProperties(BaseElement element, BytesBuffer buffer, + boolean tagged) { + if (tagged) { + this.formatProperties(element.getProperties().values(), buffer); + } else { + this.formatSchemaProperties(element, buffer); } + } - return buffer.bytes(); + private void formatElementExpiredTime(BaseElement element, BytesBuffer buffer) { + if (element.hasTtl()) { + this.formatExpiredTime(element.expiredTime(), buffer); + } } public void formatProperties(Collection> props, BytesBuffer buffer) { - // Write properties size - buffer.writeVInt(props.size()); + this.formatProperties(props, props.size(), buffer, true); + } - // Write properties data + public void formatSchemaProperties(BaseElement owner, BytesBuffer buffer) { + this.formatProperties(owner.properties().values(), owner.sizeOfProperties(), buffer, false); + } + + private void formatProperties(Iterable> props, int size, + BytesBuffer buffer, boolean tagged) { + buffer.writeVInt(size); for (BaseProperty property : props) { - PropertyKey pkey = property.propertyKey(); - buffer.writeVInt(SchemaElement.schemaId(pkey.id())); - buffer.writeProperty(pkey.cardinality(), pkey.dataType(), - property.value()); + this.formatProperty(property, buffer, tagged); + } + } + + public void formatSchemaProperty(BaseProperty property, BytesBuffer buffer) { + this.formatProperty(property, buffer, false); + } + + private void formatProperty(BaseProperty property, BytesBuffer buffer, + boolean tagged) { + PropertyKey pkey = property.propertyKey(); + buffer.writeVInt(SchemaElement.schemaId(pkey.id())); + if (tagged) { + buffer.writeProperty(pkey, property.value()); + } else { + buffer.writeSchemaProperty(pkey, property.value()); } } @@ -527,7 +734,7 @@ public void formatExpiredTime(long expiredTime, BytesBuffer buffer) { buffer.writeVLong(expiredTime); } - protected void parseExpiredTime(BytesBuffer buffer, BaseElement element) { + public void parseExpiredTime(BytesBuffer buffer, BaseElement element) { element.expiredTime(buffer.readVLong()); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BytesBuffer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BytesBuffer.java index 4ec6aad194..050ad75031 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BytesBuffer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/BytesBuffer.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.serializer; @@ -28,11 +26,11 @@ import java.util.LinkedHashSet; import java.util.UUID; -import org.apache.hugegraph.backend.BinaryId; import org.apache.hugegraph.id.EdgeId; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.id.Id.IdType; import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.backend.BinaryId; import org.apache.hugegraph.struct.schema.PropertyKey; import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Cardinality; @@ -41,6 +39,7 @@ import org.apache.hugegraph.util.Blob; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.KryoUtil; import org.apache.hugegraph.util.StringEncoding; /** @@ -55,31 +54,44 @@ public class BytesBuffer extends OutputStream { public static final int CHAR_LEN = Character.BYTES; public static final int FLOAT_LEN = Float.BYTES; public static final int DOUBLE_LEN = Double.BYTES; - public static final int BLOB_LEN = 4; + public static final int BYTES_LEN = 4; + public static final int BLOB_LEN = 5; public static final int UINT8_MAX = ((byte) -1) & 0xff; public static final int UINT16_MAX = ((short) -1) & 0xffff; public static final long UINT32_MAX = (-1) & 0xffffffffL; - public static final long WRITE_BYTES_MAX_LENGTH = 10 * Bytes.MB; + // TODO: support user-defined configuration // NOTE: +1 to let code 0 represent length 1 - public static final int ID_LEN_MAX = 0x7fff + 1; + public static final int ID_LEN_MAX = 0x3fff + 1; // 16KB + public static final int EID_LEN_MAX = 64 * 1024; public static final int BIG_ID_LEN_MAX = 0xfffff + 1; public static final byte STRING_ENDING_BYTE = (byte) 0x00; public static final byte STRING_ENDING_BYTE_FF = (byte) 0xff; + + // TODO: support user-defined configuration + public static final long BYTES_LEN_MAX = 10 * Bytes.MB; + public static final long WRITE_BYTES_MAX_LENGTH = BYTES_LEN_MAX; public static final int STRING_LEN_MAX = UINT16_MAX; - public static final long BLOB_LEN_MAX = Bytes.GB; + public static final long BLOB_LEN_MAX = 1 * Bytes.GB; + + public static final int MAX_PROPERTIES = BytesBuffer.UINT16_MAX; // The value must be in range [8, ID_LEN_MAX] public static final int INDEX_HASH_ID_THRESHOLD = 32; public static final int DEFAULT_CAPACITY = 64; public static final int MAX_BUFFER_CAPACITY = 128 * 1024 * 1024; // 128M + public static final int MAX_BUFFER_CAPACITY_UPPER_BOUND = (int) Bytes.GB; public static final int BUF_EDGE_ID = 128; public static final int BUF_PROPERTY = 64; + public static final byte[] BYTES_EMPTY = new byte[0]; + + private static volatile Integer maxBufferCapacity; + private ByteBuffer buffer; private final boolean resize; @@ -88,9 +100,12 @@ public BytesBuffer() { } public BytesBuffer(int capacity) { - E.checkArgument(capacity <= MAX_BUFFER_CAPACITY, - "Capacity exceeds max buffer capacity: %s", - MAX_BUFFER_CAPACITY); + int maxCapacity = maxBufferCapacity(); + if (capacity > maxCapacity) { + E.checkArgument(false, + "Capacity %s exceeds max buffer capacity: %s", + capacity, maxCapacity); + } this.buffer = ByteBuffer.allocate(capacity); this.resize = true; } @@ -117,6 +132,43 @@ public static BytesBuffer wrap(byte[] array, int offset, int length) { return new BytesBuffer(ByteBuffer.wrap(array, offset, length)); } + public static int maxBufferCapacity() { + Integer capacity = maxBufferCapacity; + return capacity != null ? capacity : MAX_BUFFER_CAPACITY; + } + + public static synchronized void initMaxBufferCapacity(int capacity) { + initMaxBufferCapacity(capacity, true); + } + + public static synchronized void initMaxBufferCapacity(int capacity, + boolean explicit) { + E.checkArgument(capacity >= DEFAULT_CAPACITY && + capacity <= MAX_BUFFER_CAPACITY_UPPER_BOUND, + "Max buffer capacity must be in range [%s, %s], " + + "but got %s", + DEFAULT_CAPACITY, MAX_BUFFER_CAPACITY_UPPER_BOUND, + capacity); + + if (!explicit) { + return; + } + + if (maxBufferCapacity == null) { + maxBufferCapacity = capacity; + return; + } + + if (maxBufferCapacity == capacity) { + return; + } + + throw new IllegalArgumentException(String.format( + "The process-wide serializer buffer max capacity has been " + + "initialized to %s, but got conflicting value %s", + maxBufferCapacity, capacity)); + } + public ByteBuffer asByteBuffer() { return this.buffer; } @@ -160,18 +212,26 @@ public int remaining() { private void require(int size) { // Does need to resize? - if (this.buffer.limit() - this.buffer.position() >= size) { + if (this.buffer.remaining() >= size) { return; } // Can't resize for wrapped buffer since will change the origin ref - E.checkState(this.resize, "Can't resize for wrapped buffer"); + if (!this.resize) { + E.checkState(false, "Can't resize for wrapped buffer"); + } + + int maxCapacity = maxBufferCapacity(); + long requiredCapacity = (long) this.buffer.position() + size; + if (requiredCapacity > maxCapacity) { + E.checkArgument(false, + "Capacity %s exceeds max buffer capacity: %s", + requiredCapacity, maxCapacity); + } // Extra capacity as buffer - int newcapacity = size + this.buffer.limit() + DEFAULT_CAPACITY; - E.checkArgument(newcapacity <= MAX_BUFFER_CAPACITY, - "Capacity exceeds max buffer capacity: %s", - MAX_BUFFER_CAPACITY); - ByteBuffer newBuffer = ByteBuffer.allocate(newcapacity); + long newCapacity = Math.min(requiredCapacity + DEFAULT_CAPACITY, + maxCapacity); + ByteBuffer newBuffer = ByteBuffer.allocate((int) newCapacity); this.buffer.flip(); newBuffer.put(this.buffer); this.buffer = newBuffer; @@ -248,7 +308,7 @@ public byte peek() { } public byte peekLast() { - return this.buffer.get(this.buffer.capacity() - 1); + return this.buffer.get(this.buffer.limit() - 1); } public byte read() { @@ -261,12 +321,6 @@ public byte[] read(int length) { return bytes; } - public byte[] readToEnd() { - byte[] bytes = new byte[this.remaining()]; - this.buffer.get(bytes); - return bytes; - } - public boolean readBoolean() { return this.buffer.get() != 0; } @@ -296,12 +350,12 @@ public double readDouble() { } public BytesBuffer writeBytes(byte[] bytes) { - // Original limit as above, consider this limit may be due to performance considerations when multiple storage backends are used. - // The above limit will cause errors when writing value to property exceeds the limit. So adjust size to 5M - E.checkArgument(bytes.length <= WRITE_BYTES_MAX_LENGTH, - "The max length of bytes is %s, but got %s", - WRITE_BYTES_MAX_LENGTH, bytes.length); - require(SHORT_LEN + bytes.length); + if (bytes.length > BYTES_LEN_MAX) { + E.checkArgument(false, + "The max length of bytes is %s, but got %s", + BYTES_LEN_MAX, bytes.length); + } + require(BYTES_LEN + bytes.length); this.writeVInt(bytes.length); this.write(bytes); return this; @@ -310,14 +364,15 @@ public BytesBuffer writeBytes(byte[] bytes) { public byte[] readBytes() { int length = this.readVInt(); assert length >= 0; - byte[] bytes = this.read(length); - return bytes; + return this.read(length); } public BytesBuffer writeBigBytes(byte[] bytes) { - E.checkArgument(bytes.length <= BLOB_LEN_MAX, - "The max length of bytes is %s, but got %s", - BLOB_LEN_MAX, bytes.length); + if (bytes.length > BLOB_LEN_MAX) { + E.checkArgument(false, + "The max length of bytes is %s, but got %s", + BLOB_LEN_MAX, bytes.length); + } require(BLOB_LEN + bytes.length); this.writeVInt(bytes.length); this.write(bytes); @@ -327,8 +382,7 @@ public BytesBuffer writeBigBytes(byte[] bytes) { public byte[] readBigBytes() { int length = this.readVInt(); assert length >= 0; - byte[] bytes = this.read(length); - return bytes; + return this.read(length); } public BytesBuffer writeStringRaw(String val) { @@ -356,11 +410,9 @@ public BytesBuffer writeStringWithEnding(String value) { * 0xFF is not a valid byte in UTF8 bytes */ assert !Bytes.contains(bytes, STRING_ENDING_BYTE_FF) : - "Invalid UTF8 bytes: " + value; + "Invalid UTF8 bytes: " + value; if (Bytes.contains(bytes, STRING_ENDING_BYTE)) { - E.checkArgument(false, - "Can't contains byte '0x00' in string: '%s'", - value); + E.checkArgument(false, "Can't contains byte '0x00' in string: '%s'", value); } this.write(bytes); } @@ -378,17 +430,6 @@ public BytesBuffer writeStringWithEnding(String value) { public String readStringWithEnding() { return StringEncoding.decode(this.readBytesWithEnding()); } - public String skipBytesWithEnding(){ - boolean foundEnding = false; - while (this.remaining() > 0) { - byte current = this.read(); - if (current == STRING_ENDING_BYTE) { - foundEnding = true; - break; - } - } - return ""; - } public BytesBuffer writeStringToRemaining(String value) { byte[] bytes = StringEncoding.encode(value); @@ -444,7 +485,7 @@ public BytesBuffer writeVInt(int value) { this.write(0x80 | ((value >>> 14) & 0x7f)); } if (value > 0x7f || value < 0) { - this.write(0x80 | ((value >>> 7) & 0x7f)); + this.write(0x80 | ((value >>> 7) & 0x7f)); } this.write(value & 0x7f); @@ -453,6 +494,11 @@ public BytesBuffer writeVInt(int value) { public int readVInt() { byte leading = this.read(); + if (leading == 0x80) { + E.checkArgument(false, + "Unexpected varint with leading byte '0x%s'", + Bytes.toHex(leading)); + } int value = leading & 0x7f; if (leading >= 0) { assert (leading & 0x80) == 0; @@ -470,6 +516,16 @@ public int readVInt() { } } + if (i >= 5) { + E.checkArgument(false, + "Unexpected varint %s with too many bytes(%s)", + value, i + 1); + } + if (i >= 4 && (leading & 0x70) != 0) { + E.checkArgument(false, + "Unexpected varint %s with leading byte '0x%s'", + value, Bytes.toHex(leading)); + } return value; } @@ -499,7 +555,7 @@ public BytesBuffer writeVLong(long value) { this.write(0x80 | ((int) (value >>> 14) & 0x7f)); } if (value > 0x7fL || value < 0L) { - this.write(0x80 | ((int) (value >>> 7) & 0x7f)); + this.write(0x80 | ((int) (value >>> 7) & 0x7f)); } this.write((int) value & 0x7f); @@ -508,9 +564,11 @@ public BytesBuffer writeVLong(long value) { public long readVLong() { byte leading = this.read(); - E.checkArgument(leading != 0x80, - "Unexpected varlong with leading byte '0x%s'", - Bytes.toHex(leading)); + if (leading == 0x80) { + E.checkArgument(false, + "Unexpected varlong with leading byte '0x%s'", + Bytes.toHex(leading)); + } long value = leading & 0x7fL; if (leading >= 0) { assert (leading & 0x80) == 0; @@ -528,84 +586,99 @@ public long readVLong() { } } - E.checkArgument(i < 10, - "Unexpected varlong %s with too many bytes(%s)", - value, i + 1); - E.checkArgument(i < 9 || (leading & 0x7e) == 0, - "Unexpected varlong %s with leading byte '0x%s'", - value, Bytes.toHex(leading)); + if (i >= 10) { + E.checkArgument(false, + "Unexpected varlong %s with too many bytes(%s)", + value, i + 1); + } + if (i >= 9 && (leading & 0x7e) != 0) { + E.checkArgument(false, + "Unexpected varlong %s with leading byte '0x%s'", + value, Bytes.toHex(leading)); + } return value; } - public T newValue(Cardinality cardinality) { - switch (cardinality) { - case SET: - return (T) new LinkedHashSet<>(); - case LIST: - return (T) new ArrayList<>(); - default: - // pass - break; - } - return null; + /** + * Store properties carry their cardinality and type in a leading byte. + * Schema-driven backend properties use {@link #writeSchemaProperty}. + */ + public BytesBuffer writeProperty(PropertyKey pkey, Object value) { + return this.writeProperty(pkey.cardinality(), pkey.dataType(), value); } - private byte getCardinalityAndType(int cardinality, int type){ - return (byte) ((cardinality << 6) | type); + public BytesBuffer writeProperty(Cardinality cardinality, DataType dataType, + Object value) { + this.write((cardinality.code() << 6) | dataType.code()); + return this.writePropertyValue(cardinality, dataType, value); } - public static byte getCardinality(int value){ - return (byte) ((value & 0xc0) >> 6); + public Object readProperty(PropertyKey pkey) { + int metadata = this.readUInt8(); + Cardinality cardinality = SerialEnum.fromCode(Cardinality.class, + getCardinality(metadata)); + DataType dataType = SerialEnum.fromCode(DataType.class, getType(metadata)); + pkey.cardinality(cardinality); + pkey.dataType(dataType); + return this.readPropertyValue(cardinality, dataType); } - public static byte getType(int value){ - return (byte) (value & 0x3f); + /** + * Encode a backend property whose metadata is supplied by the schema. + * Unlike Store's tagged format, no metadata byte is persisted here. + */ + public BytesBuffer writeSchemaProperty(PropertyKey pkey, Object value) { + return this.writePropertyValue(pkey.cardinality(), pkey.dataType(), value); } - public BytesBuffer writeProperty(PropertyKey pkey, Object value) { - return writeProperty(pkey.cardinality(), pkey.dataType(), value); + public Object readSchemaProperty(PropertyKey pkey) { + return this.readPropertyValue(pkey.cardinality(), pkey.dataType()); } - public BytesBuffer writeProperty(Cardinality cardinality, DataType dataType, Object value) { - this.write(getCardinalityAndType(cardinality.code(),dataType.code())); + private BytesBuffer writePropertyValue(Cardinality cardinality, + DataType dataType, Object value) { if (cardinality == Cardinality.SINGLE) { this.writeProperty(dataType, value); return this; } - assert cardinality == Cardinality.LIST || - cardinality == Cardinality.SET; + assert cardinality == Cardinality.LIST || cardinality == Cardinality.SET; Collection values = (Collection) value; this.writeVInt(values.size()); - for (Object o : values) { - this.writeProperty(dataType, o); + for (Object item : values) { + this.writeProperty(dataType, item); } return this; } - public Object readProperty(PropertyKey propertyKey) { - byte cardinalityAndType = this.read(); - Cardinality cardinality; - DataType type; - cardinality = SerialEnum.fromCode(Cardinality.class, - getCardinality(cardinalityAndType)); - - type = SerialEnum.fromCode(DataType.class, getType(cardinalityAndType)); - propertyKey.cardinality(cardinality); - propertyKey.dataType(type); + private Object readPropertyValue(Cardinality cardinality, DataType dataType) { if (cardinality == Cardinality.SINGLE) { - Object value = this.readProperty(type); - return value; + return this.readProperty(dataType); } - Collection values = this.newValue(cardinality); - assert cardinality == Cardinality.LIST || - cardinality == Cardinality.SET; + assert cardinality == Cardinality.LIST || cardinality == Cardinality.SET; int size = this.readVInt(); + Collection values = this.newValue(cardinality); for (int i = 0; i < size; i++) { - values.add(this.readProperty(type)); + values.add(this.readProperty(dataType)); } return values; } + @SuppressWarnings("unchecked") + public T newValue(Cardinality cardinality) { + switch (cardinality) { + case SET: + return (T) new LinkedHashSet<>(); + case LIST: + return (T) new ArrayList<>(); + default: + return null; + } + } + + public static byte getCardinality(int value) { + return (byte) ((value & 0xc0) >> 6); + } + public void writeProperty(DataType dataType, Object value) { switch (dataType) { case BOOLEAN: @@ -633,8 +706,7 @@ public void writeProperty(DataType dataType, Object value) { this.writeString((String) value); break; case BLOB: - byte[] bytes = value instanceof byte[] ? - (byte[]) value : ((Blob) value).bytes(); + byte[] bytes = value instanceof byte[] ? (byte[]) value : ((Blob) value).bytes(); this.writeBigBytes(bytes); break; case UUID: @@ -644,10 +716,15 @@ public void writeProperty(DataType dataType, Object value) { this.writeLong(uuid.getLeastSignificantBits()); break; default: - throw new IllegalArgumentException("Unsupported data type " + dataType); + this.writeBytes(KryoUtil.toKryoWithType(value)); + break; } } + public static byte getType(int value) { + return (byte) (value & 0x3f); + } + public Object readProperty(DataType dataType) { switch (dataType) { case BOOLEAN: @@ -671,15 +748,69 @@ public Object readProperty(DataType dataType) { case UUID: return new UUID(this.readLong(), this.readLong()); default: - throw new IllegalArgumentException("Unsupported data type " + dataType); + return KryoUtil.fromKryoWithType(this.readBytes()); } } - public BytesBuffer writeId(Id id) { - return this.writeId(id, false); + /** Skip a tagged property without allocating its value or collection. */ + public void skipProperty() { + int metadata = this.readUInt8(); + Cardinality cardinality = SerialEnum.fromCode(Cardinality.class, + getCardinality(metadata)); + DataType dataType = SerialEnum.fromCode(DataType.class, getType(metadata)); + this.skipPropertyValue(cardinality, dataType); } - public BytesBuffer writeId(Id id, boolean big) { + public void skipSchemaProperty(PropertyKey pkey) { + this.skipPropertyValue(pkey.cardinality(), pkey.dataType()); + } + + private void skipPropertyValue(Cardinality cardinality, DataType dataType) { + if (cardinality == Cardinality.SINGLE) { + this.skipProperty(dataType); + return; + } + assert cardinality == Cardinality.LIST || cardinality == Cardinality.SET; + int size = this.readVInt(); + E.checkArgument(size >= 0, "Invalid property collection size: %s", size); + for (int i = 0; i < size; i++) { + this.skipProperty(dataType); + } + } + + private void skipProperty(DataType dataType) { + switch (dataType) { + case BOOLEAN: + case BYTE: + case INT: + this.readVInt(); + return; + case LONG: + case DATE: + this.readVLong(); + return; + case FLOAT: + this.skip(FLOAT_LEN); + return; + case DOUBLE: + this.skip(DOUBLE_LEN); + return; + case UUID: + this.skip(Id.UUID_LENGTH); + return; + default: + // Text, blob and Kryo fallback payloads all carry a byte length. + this.skip(this.readVInt()); + } + } + + private void skip(int length) { + E.checkArgument(length >= 0 && length <= this.remaining(), + "Invalid skipped byte length %s, remaining %s", length, this.remaining()); + this.buffer.position(this.buffer.position() + length); + } + + public BytesBuffer writeId(Id id) { switch (id.type()) { case LONG: // Number Id @@ -687,35 +818,39 @@ public BytesBuffer writeId(Id id, boolean big) { this.writeNumber(value); break; case UUID: - // UUID Id + // UUID ID byte[] bytes = id.asBytes(); assert bytes.length == Id.UUID_LENGTH; this.writeUInt8(0x7f); // 0b01111111 means UUID this.write(bytes); break; case EDGE: - // Edge Id + // Edge ID this.writeUInt8(0x7e); // 0b01111110 means EdgeId this.writeEdgeId(id); break; default: - // String Id + // String Id (VertexID) bytes = id.asBytes(); int len = bytes.length; - E.checkArgument(len > 0, "Can't write empty id"); - E.checkArgument(len <= 16384, - "Big id max length is %s, but got %s {%s}", - 16384, len, id); - len -= 1; - if (len <= 63) { + if (len <= 0) { + E.checkArgument(false, "Can't write empty id"); + } + if (len > ID_LEN_MAX) { + E.checkArgument(false, "Big id max length is %s, but got %s {%s}", + ID_LEN_MAX, len, id); + } + len -= 1; // mapping [1, 16384] to [0, 16383] + if (len <= 0x3f) { + // If length is <= 63, use a single byte with the highest bit set to 1 this.writeUInt8(len | 0x80); } else { int high = len >> 8; int low = len & 0xff; + // Write high 8 bits with highest two bits set to 11 this.writeUInt8(high | 0xc0); this.writeUInt8(low); } - this.write(bytes); break; } @@ -723,10 +858,6 @@ public BytesBuffer writeId(Id id, boolean big) { } public Id readId() { - return this.readId(false); - } - - public Id readId(boolean big) { byte b = this.read(); boolean number = (b & 0x80) == 0; if (number) { @@ -742,19 +873,32 @@ public Id readId(boolean big) { } } else { // String Id - int len = b & 0x3f; - if ((b & 0x40) != 0) { + int len = b & 0x3f; // Take the lowest 6 bits as part of the length + if ((b & 0x40) != 0) { // If the 7th bit is set, length information spans 2 bytes int high = len << 8; int low = this.readUInt8(); len = high + low; } - len += 1; + len += 1; // restore [0, 16383] to [1, 16384] byte[] id = this.read(len); return IdGenerator.of(id, IdType.STRING); } } + /** + * Preserve the existing Store API. Both modes use the same persisted ID + * header; the flag has never selected a different on-disk format. + */ + public BytesBuffer writeId(Id id, boolean big) { + return this.writeId(id); + } + + public Id readId(boolean big) { + return this.readId(); + } + public BytesBuffer writeEdgeId(Id id) { + // owner-vertex + dir + edge-label + sub-edge-label + sort-values + other-vertex EdgeId edge = (EdgeId) id; this.writeId(edge.ownerVertexId()); this.write(edge.directionCode()); @@ -766,18 +910,79 @@ public BytesBuffer writeEdgeId(Id id) { } public Id readEdgeId() { - return new EdgeId(this.readId(), EdgeId.directionFromCode(this.read()), - this.readId(), this.readId(), - this.readStringWithEnding(), this.readId()); + return this.readEdgeId(true, null); + } + + public EdgeId readEdgeId(boolean withOwnerPrefix, Id suppliedOwner) { + return this.readEdgeId(withOwnerPrefix, suppliedOwner, false); + } + + private EdgeId readEdgeId(boolean withOwnerPrefix, Id suppliedOwner, boolean skipSortValues) { + Id owner = withOwnerPrefix ? this.readId() : suppliedOwner; + E.checkArgumentNotNull(owner, "Edge decoding requires an owner ID"); + byte direction = this.read(); + E.checkState(direction == HugeType.EDGE_IN.code() || direction == HugeType.EDGE_OUT.code(), + "Invalid edge column type: %s", direction & 0xff); + Id label = this.readId(); + Id subLabel = this.readId(); + String sortValues = skipSortValues ? this.skipBytesWithEnding() : this.readStringWithEnding(); + return new EdgeId(owner, EdgeId.directionFromCode(direction), label, subLabel, + sortValues, this.readId()); + } + + public enum IndexExpiryLayout { + NONE, + REQUIRED, + OPTIONAL + } + + /** Decode the shared index/element/expiry field order; callers choose the layout. */ + public IndexColumnName readIndexColumnName(HugeType type, boolean withIndexPrefix, + IndexExpiryLayout expiryLayout) { + E.checkArgumentNotNull(expiryLayout, "Index expiry layout can't be null"); + BinaryId indexId = withIndexPrefix ? this.readIndexId(type) : null; + Id elementId = this.readId(); + boolean hasExpiredTime = expiryLayout == IndexExpiryLayout.REQUIRED || + expiryLayout == IndexExpiryLayout.OPTIONAL && this.remaining() > 0; + long expiredTime = hasExpiredTime ? this.readVLong() : 0L; + if (expiryLayout == IndexExpiryLayout.OPTIONAL) { + E.checkState(this.remaining() == 0, + "Unexpected trailing bytes in schema index column: %s", this.remaining()); + } + return new IndexColumnName(indexId, elementId, expiredTime, hasExpiredTime); } - public Id readEdgeIdSkipSortValues() { - return new EdgeId(this.readId(), EdgeId.directionFromCode(this.read()), - this.readId(), this.readId(), - this.skipBytesWithEnding(), - this.readId()); - } + public static final class IndexColumnName { + + private final BinaryId indexId; + private final Id elementId; + private final long expiredTime; + private final boolean hasExpiredTime; + + private IndexColumnName(BinaryId indexId, Id elementId, long expiredTime, + boolean hasExpiredTime) { + this.indexId = indexId; + this.elementId = elementId; + this.expiredTime = expiredTime; + this.hasExpiredTime = hasExpiredTime; + } + public BinaryId indexId() { + return this.indexId; + } + + public Id elementId() { + return this.elementId; + } + + public long expiredTime() { + return this.expiredTime; + } + + public boolean hasExpiredTime() { + return this.hasExpiredTime; + } + } public BytesBuffer writeIndexId(Id id, HugeType type) { return this.writeIndexId(id, type, true); @@ -786,17 +991,18 @@ public BytesBuffer writeIndexId(Id id, HugeType type) { public BytesBuffer writeIndexId(Id id, HugeType type, boolean withEnding) { byte[] bytes = id.asBytes(); int len = bytes.length; - E.checkArgument(len > 0, "Can't write empty id"); + if (len == 0) { + E.checkArgument(false, "Can't write empty id"); + } this.write(bytes); if (type.isStringIndex()) { if (Bytes.contains(bytes, STRING_ENDING_BYTE)) { - // Not allow STRING_ENDING_BYTE exist in string index id + // Not allow STRING_ENDING_BYTE to exist in string index id E.checkArgument(false, "The %s type index id can't contains " + - "byte '0x%s', but got: 0x%s", type, - Bytes.toHex(STRING_ENDING_BYTE), - Bytes.toHex(bytes)); + "byte '0x%s', but got: 0x%s", + type, Bytes.toHex(STRING_ENDING_BYTE), Bytes.toHex(bytes)); } if (withEnding) { this.writeStringWithEnding(""); @@ -808,10 +1014,10 @@ public BytesBuffer writeIndexId(Id id, HugeType type, boolean withEnding) { public BinaryId readIndexId(HugeType type) { byte[] id; if (type.isRange4Index()) { - // HugeCodeType 1 bytes + IndexLabel 4 bytes + fieldValue 4 bytes + // HugeTypeCode 1 byte + IndexLabel 4 bytes + fieldValue 4 bytes id = this.read(9); } else if (type.isRange8Index()) { - // HugeCodeType 1 bytes + IndexLabel 4 bytes + fieldValue 8 bytes + // HugeTypeCode 1 byte + IndexLabel 4 bytes + fieldValue 8 bytes id = this.read(13); } else { assert type.isStringIndex(); @@ -825,10 +1031,17 @@ public BinaryId asId() { } public BinaryId parseId(HugeType type) { + return this.parseId(type, false); + } + + public BinaryId parseId(HugeType type, boolean enablePartition) { if (type.isIndex()) { return this.readIndexId(type); } // Parse id from bytes + if ((type.isVertex() || type.isEdge()) && enablePartition) { + this.readShort(); + } int start = this.buffer.position(); /* * Since edge id in edges table doesn't prefix with leading 0x7e, @@ -844,7 +1057,7 @@ public BinaryId parseId(HugeType type) { } /** - * Parse OLAP id + * Analyze olap id * @param type * @param isOlap * @return @@ -855,12 +1068,9 @@ public BinaryId parseOlapId(HugeType type, boolean isOlap) { } // Parse id from bytes int start = this.buffer.position(); - /** - * OLAP - * {PropertyKey}{VertexId} - */ + // OLAP {PropertyKey}{VertexId} if (isOlap) { - // First read OLAP property id + // Read olap property id first Id pkId = this.readId(); } Id id = this.readId(); @@ -939,6 +1149,11 @@ private void writeNumber(long val) { } private long readNumber(byte b) { + if ((b & 0x80) != 0) { + E.checkArgument(false, + "Not a number type with prefix byte '0x%s'", + Bytes.toHex(b)); + } // Parse the kind from byte 0kkksxxx int kind = b >>> 4; boolean positive = (b & 0x08) > 0; @@ -986,27 +1201,48 @@ private long readNumber(byte b) { private byte[] readBytesWithEnding() { int start = this.buffer.position(); boolean foundEnding = false; - while (this.remaining() > 0) { + int remaining = this.remaining(); + for (int i = 0; i < remaining; i++) { byte current = this.read(); if (current == STRING_ENDING_BYTE) { foundEnding = true; break; } } - E.checkArgument(foundEnding, "Not found ending '0x%s'", - Bytes.toHex(STRING_ENDING_BYTE)); + if (!foundEnding) { + E.checkArgument(false, + "Not found ending '0x%s'", + Bytes.toHex(STRING_ENDING_BYTE)); + } int end = this.buffer.position() - 1; int len = end - start; + if (len <= 0) { + return BYTES_EMPTY; + } byte[] bytes = new byte[len]; System.arraycopy(this.array(), start, bytes, 0, len); return bytes; } - public byte[] remainingBytes(){ - int length = this.remaining(); + public byte[] readToEnd() { + return this.read(this.remaining()); + } + + public String skipBytesWithEnding() { + while (this.remaining() > 0) { + if (this.read() == STRING_ENDING_BYTE) { + break; + } + } + return ""; + } + + public Id readEdgeIdSkipSortValues() { + return this.readEdgeId(true, null, true); + } + + public byte[] remainingBytes() { int start = this.position(); - byte[] bytes = new byte[length]; - System.arraycopy(this.array(), start, bytes, 0, length); - return bytes; + return Arrays.copyOfRange(this.array(), start, start + this.remaining()); } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/DirectBinarySerializer.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/DirectBinarySerializer.java index bad18ebf8a..8aa325eabe 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/DirectBinarySerializer.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/DirectBinarySerializer.java @@ -22,9 +22,13 @@ import java.util.Arrays; import java.util.Base64; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.id.IdGenerator; -import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.Log; import org.slf4j.Logger; @@ -111,18 +115,56 @@ public DirectHugeElement parseEdge(byte[] key, byte[] value) { return new DirectHugeElement(IdGenerator.of(key), expiredTime); } + public DirectHugeElement parseSchemaIndex(HugeGraphSupplier graph, byte[] key, byte[] value) { + Index index = BinaryElementSerializer.getInstance().parseSchemaIndex( + graph, BackendColumn.of(key, value)); + return new DirectHugeElement(IdGenerator.of(key), index.expiredTime()); + } + + /** Read TTL from an untagged persisted Server vertex row. */ + public DirectHugeElement parseSchemaVertex(HugeGraphSupplier graph, byte[] key, byte[] value) { + E.checkArgumentNotNull(graph, "Schema vertex decoding requires a schema supplier"); + BytesBuffer buffer = BytesBuffer.wrap(value); + Id labelId = buffer.readId(); + this.skipProperties(buffer, graph); + long expiredTime = graph.vertexLabelOrNone(labelId).ttl() > 0 ? buffer.readVLong() : 0L; + return new DirectHugeElement(IdGenerator.of(key), expiredTime); + } + + /** Read TTL from an untagged persisted Server edge row. */ + public DirectHugeElement parseSchemaEdge(HugeGraphSupplier graph, byte[] key, byte[] value) { + E.checkArgumentNotNull(graph, "Schema edge decoding requires a schema supplier"); + BytesBuffer name = BytesBuffer.wrap(key); + name.readId(); + byte type = name.read(); + E.checkState(type == HugeType.EDGE_IN.code() || type == HugeType.EDGE_OUT.code(), + "Invalid edge column type: %s", type & 0xff); + name.readId(); + Id subLabelId = name.readId(); + BytesBuffer buffer = BytesBuffer.wrap(value); + this.skipProperties(buffer, graph); + long expiredTime = graph.edgeLabelOrNone(subLabelId).ttl() > 0 ? buffer.readVLong() : 0L; + return new DirectHugeElement(IdGenerator.of(key), expiredTime); + } + private void skipProperties(BytesBuffer buffer) { + this.skipProperties(buffer, null); + } + + private void skipProperties(BytesBuffer buffer, HugeGraphSupplier graph) { int size = buffer.readVInt(); assert size >= 0; for (int i = 0; i < size; i++) { Id pkeyId = IdGenerator.of(buffer.readVInt()); - this.skipProperty(pkeyId, buffer); + if (graph == null) { + this.skipProperty(pkeyId, buffer); + } else { + buffer.skipSchemaProperty(graph.propertyKey(pkeyId)); + } } } protected void skipProperty(Id pkeyId, BytesBuffer buffer) { - // Parse value - PropertyKey pkey = new PropertyKey(null, pkeyId, ""); - buffer.readProperty(pkey); + buffer.skipProperty(); } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/OlapKey.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/OlapKey.java new file mode 100644 index 0000000000..814aea66e9 --- /dev/null +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/serializer/OlapKey.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.serializer; + +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.struct.schema.SchemaElement; + +/** Physical keys for the merged HStore OLAP table, independent of the value codec. */ +public final class OlapKey { + + private OlapKey() { + } + + public static byte[] format(Id propertyId, Id vertexId) { + return BytesBuffer.allocate(propertyId.length() + vertexId.length() + 18) + .writeId(propertyId).writeId(vertexId).bytes(); + } + + public static boolean matchesProperty(byte[] value, Id propertyId) { + if (value == null || value.length == 0) { + return false; + } + try { + return BytesBuffer.wrap(value).readVInt() == SchemaElement.schemaId(propertyId); + } catch (IllegalArgumentException | java.nio.BufferUnderflowException e) { + return false; + } + } +} diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/EdgeLabel.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/EdgeLabel.java index 7148495a78..128f8f4f63 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/EdgeLabel.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/EdgeLabel.java @@ -332,6 +332,7 @@ public static EdgeLabel fromMap(Map map, HugeGraphSupplier graph Id id = IdGenerator.of((int) map.get(EdgeLabel.P.ID)); String name = (String) map.get(EdgeLabel.P.NAME); EdgeLabel edgeLabel = new EdgeLabel(graph, id, name); + restoreLinks(map, edgeLabel); for (Map.Entry entry : map.entrySet()) { switch (entry.getKey()) { case P.ID: @@ -373,25 +374,9 @@ public static EdgeLabel fromMap(Map map, HugeGraphSupplier graph edgeLabel.ttlStartTime(IdGenerator.of(ttlStartTime)); break; case P.LINKS: - // TODO: serialize and deserialize - List list = (List) entry.getValue(); - for (Map m : list) { - for (Object key : m.keySet()) { - Id sid = IdGenerator.of(Long.parseLong((String) key)); - Id tid = IdGenerator.of(Long.parseLong(String.valueOf(m.get(key)))); - edgeLabel.links(Pair.of(sid, tid)); - } - } - break; case P.SOURCE_LABEL: - long sourceLabel = - Long.parseLong((String) entry.getValue()); - edgeLabel.sourceLabel(IdGenerator.of(sourceLabel)); - break; case P.TARGET_LABEL: - long targetLabel = - Long.parseLong((String) entry.getValue()); - edgeLabel.targetLabel(IdGenerator.of(targetLabel)); + // These fields describe the same links and were restored together. break; case P.FATHER_ID: long fatherId = @@ -410,9 +395,9 @@ public static EdgeLabel fromMap(Map map, HugeGraphSupplier graph edgeLabel.frequency(frequency); break; case P.SORT_KEYS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - edgeLabel.sortKeys(ids.toArray(new Id[0])); + List orderedIds = ((List) entry.getValue()).stream().map( + IdGenerator::of).collect(Collectors.toList()); + edgeLabel.sortKeys(orderedIds.toArray(new Id[0])); break; default: throw new AssertionError(String.format( @@ -423,6 +408,48 @@ public static EdgeLabel fromMap(Map map, HugeGraphSupplier graph return edgeLabel; } + private static void restoreLinks(Map map, EdgeLabel edgeLabel) { + Set> links = new HashSet<>(); + if (map.containsKey(P.LINKS)) { + Object value = map.get(P.LINKS); + E.checkArgument(value instanceof List, "Invalid edge label links: %s", value); + for (Object item : (List) value) { + E.checkArgument(item instanceof Map && !((Map) item).isEmpty(), + "Invalid edge label link: %s", item); + for (Map.Entry link : ((Map) item).entrySet()) { + links.add(Pair.of(linkId(link.getKey(), P.SOURCE_LABEL), + linkId(link.getValue(), P.TARGET_LABEL))); + } + } + } + + boolean hasSource = map.containsKey(P.SOURCE_LABEL); + boolean hasTarget = map.containsKey(P.TARGET_LABEL); + E.checkArgument(hasSource == hasTarget, + "Edge label sourceLabel and targetLabel must be provided together"); + if (hasSource) { + Pair endpoints = Pair.of(linkId(map.get(P.SOURCE_LABEL), P.SOURCE_LABEL), + linkId(map.get(P.TARGET_LABEL), P.TARGET_LABEL)); + E.checkArgument(links.isEmpty() || links.contains(endpoints), + "Edge label endpoints %s conflict with links %s", endpoints, links); + links.add(endpoints); + } + for (Pair link : links) { + edgeLabel.links(link); + } + } + + private static Id linkId(Object value, String field) { + E.checkArgument(value instanceof String || value instanceof Number, + "Invalid edge label %s: %s", field, value); + try { + return IdGenerator.of(Long.parseLong(value.toString())); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format( + "Invalid edge label %s: %s", field, value), e); + } + } + public static final class P { public static final String ID = "id"; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/IndexLabel.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/IndexLabel.java index 2ef5eb9962..282d9ea79f 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/IndexLabel.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/IndexLabel.java @@ -126,7 +126,7 @@ public SchemaLabel baseLabel() { } public SchemaLabel baseElement() { - return getElement(this.graph, this.baseType, this.baseValue); + return getBaseLabel(this.graph, this.baseType, this.baseValue); } public boolean hasSameContent(IndexLabel other) { @@ -258,44 +258,6 @@ public static SchemaLabel getBaseLabel(HugeGraphSupplier graph, return label; } - public static SchemaLabel getElement(HugeGraphSupplier graph, - HugeType baseType, Object baseValue) { - E.checkNotNull(baseType, "base type", "index label"); - E.checkNotNull(baseValue, "base value", "index label"); - E.checkArgument(baseValue instanceof String || baseValue instanceof Id, - "The base value must be instance of String or Id, " + - "but got %s(%s)", baseValue, - baseValue.getClass().getSimpleName()); - - SchemaLabel label; - switch (baseType) { - case VERTEX_LABEL: - if (baseValue instanceof String) { - label = graph.vertexLabel((String) baseValue); - } else { - assert baseValue instanceof Id; - label = graph.vertexLabel((Id) baseValue); - } - break; - case EDGE_LABEL: - if (baseValue instanceof String) { - label = graph.edgeLabel((String) baseValue); - } else { - assert baseValue instanceof Id; - label = graph.edgeLabel((Id) baseValue); - } - break; - default: - throw new AssertionError(String.format( - "Unsupported base type '%s' of index label", - baseType)); - } - - E.checkArgumentNotNull(label, "Can't find the %s with name '%s'", - baseType.readableName(), baseValue); - return label; - } - public String convert2Groovy(boolean attachIdFlag) { StringBuilder builder = new StringBuilder(SCHEMA_PREFIX); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/SchemaElement.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/SchemaElement.java index a62532ff79..d2563e34e9 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/SchemaElement.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/SchemaElement.java @@ -76,6 +76,8 @@ public SchemaElement(final HugeGraphSupplier graph, Id id, String name) { } public HugeGraphSupplier graph() { + E.checkState(this.graph != null, + "Graph is null of schema '%s'", this.name); return this.graph; } @@ -103,10 +105,12 @@ public void userdata(String key, Object value) { } public void userdata(Userdata userdata) { + E.checkArgumentNotNull(userdata, "userdata"); this.userdata.putAll(userdata); } public void userdata(Map userdata) { + E.checkArgumentNotNull(userdata, "userdata"); this.userdata.putAll(userdata); } @@ -116,6 +120,7 @@ public void removeUserdata(String key) { } public void removeUserdata(Userdata userdata) { + E.checkArgumentNotNull(userdata, "userdata"); for (String key : userdata.keySet()) { this.userdata.remove(key); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/Userdata.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/Userdata.java index 1cd0db0e0f..8aef1e5610 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/Userdata.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/Userdata.java @@ -22,6 +22,7 @@ import org.apache.hugegraph.exception.NotAllowException; import org.apache.hugegraph.type.define.Action; +import org.apache.hugegraph.util.DateUtil; public class Userdata extends HashMap { @@ -37,6 +38,51 @@ public Userdata(Map map) { this.putAll(map); } + /** + * Normalizes the value before storing so the {@link #CREATE_TIME}-is-Date + * invariant holds regardless of how entries are added. + */ + @Override + public Object put(String key, Object value) { + return super.put(key, normalizeValue(key, value)); + } + + @Override + public void putAll(Map map) { + for (Map.Entry e : map.entrySet()) { + this.put(e.getKey(), e.getValue()); + } + } + + /** + * Normalize internal userdata values whose runtime type can diverge from + * their serialized form. The only such key today is {@link #CREATE_TIME}: + * it is written as a {@link java.util.Date} but persisted as a formatted + * JSON string by the backend serializers, and Jackson cannot re-type a + * value to {@code Date} when the target is a raw {@code Map}. This method + * restores the original type after deserialization. Idempotent for values + * already of the expected type. + *

+ * An empty string is passed through unchanged: it is the key-only + * placeholder used by the {@code eliminate()}/{@code DELETE} builder flow + * (e.g. {@code .userdata(CREATE_TIME, "").eliminate()}), where the value is + * ignored and only the key drives {@code removeUserdata}. Parsing it would + * fail before the eliminate path can apply its key-only semantics. + */ + public static Object normalizeValue(String key, Object value) { + if (CREATE_TIME.equals(key) && value instanceof String && + !((String) value).isEmpty()) { + try { + return DateUtil.parse((String) value); + } catch (RuntimeException e) { + throw new IllegalArgumentException(String.format( + "Invalid userdata '%s' value: '%s'", + CREATE_TIME, value), e); + } + } + return value; + } + public static void check(Userdata userdata, Action action) { if (userdata == null) { return; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/VertexLabel.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/VertexLabel.java index 2a0002e69d..6b0b3cfe77 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/VertexLabel.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/struct/schema/VertexLabel.java @@ -380,9 +380,9 @@ public static VertexLabel fromMap(Map map, HugeGraphSupplier gra vertexLabel.idStrategy(idStrategy); break; case P.PRIMARY_KEYS: - ids = ((List) entry.getValue()).stream().map( - IdGenerator::of).collect(Collectors.toSet()); - vertexLabel.primaryKeys(ids.toArray(new Id[0])); + List orderedIds = ((List) entry.getValue()).stream().map( + IdGenerator::of).collect(Collectors.toList()); + vertexLabel.primaryKeys(orderedIds.toArray(new Id[0])); break; default: throw new AssertionError(String.format( diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseEdge.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseEdge.java index bafc2b727a..8032be1aff 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseEdge.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseEdge.java @@ -26,7 +26,7 @@ import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.id.EdgeId; import org.apache.hugegraph.id.Id; -import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.serializer.BytesBuffer; import org.apache.hugegraph.struct.schema.EdgeLabel; import org.apache.hugegraph.struct.schema.SchemaLabel; @@ -73,7 +73,8 @@ public EdgeId idWithDirection() { @Override public String name() { if (this.name == null) { - this.name = SplicingIdGenerator.concatValues(sortValues()); + List values = this.sortValues(); + this.name = values.isEmpty() ? "" : ConditionQuery.concatValues(values); } return this.name; } @@ -98,7 +99,11 @@ public List sortValues() { BaseProperty property = this.getProperty(sk); E.checkState(property != null, "The value of sort key '%s' can't be null", sk); - propValues.add(property.propertyKey().serialValue(property.value(), true)); + Object value = property.serialValue(true); + if ("".equals(value)) { + value = ConditionQuery.INDEX_VALUE_EMPTY; + } + propValues.add(value); } return propValues; } @@ -182,9 +187,9 @@ public void assignId() { if (this.fresh()) { int len = this.id().length(); - E.checkArgument(len <= BytesBuffer.BIG_ID_LEN_MAX, + E.checkArgument(len <= BytesBuffer.EID_LEN_MAX, "The max length of edge id is %s, but got %s {%s}", - BytesBuffer.BIG_ID_LEN_MAX, len, this.id()); + BytesBuffer.EID_LEN_MAX, len, this.id()); } } @Override @@ -238,29 +243,78 @@ public BaseEdge switchOwner() { return edge; } + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (!(object instanceof BaseEdge) || this.id() == null) { + return false; + } + return this.id().equals(((BaseEdge) object).id()); + } + + @Override + public int hashCode() { + return this.id() == null ? System.identityHashCode(this) : this.id().hashCode(); + } + public static BaseEdge constructEdge(HugeGraphSupplier graph, BaseVertex ownerVertex, boolean isOutEdge, EdgeLabel edgeLabel, String sortValues, Id otherVertexId) { + BaseEdge edge = createEdge(graph, ownerVertex, isOutEdge, edgeLabel, + sortValues, otherVertexId); + ownerVertex.addEdge(edge); + edge.otherVertex().addEdge(edge.switchOwner()); + return edge; + } + + /** Create endpoint/schema state; adapters own adjacency attachment. */ + public static BaseEdge createEdge(HugeGraphSupplier graph, + BaseVertex ownerVertex, + boolean isOutEdge, + EdgeLabel edgeLabel, + String sortValues, + Id otherVertexId) { Id ownerLabelId = edgeLabel.sourceLabel(); Id otherLabelId = edgeLabel.targetLabel(); VertexLabel srcLabel; VertexLabel tgtLabel; if (graph == null) { - srcLabel = new VertexLabel(null, ownerLabelId, "UNDEF"); - tgtLabel = new VertexLabel(null, otherLabelId, "UNDEF"); + return createEdgeWithoutSchema(null, ownerVertex, isOutEdge, edgeLabel, + sortValues, otherVertexId); + } + if (edgeLabel.general() && + ownerVertex.typeContext() == BaseVertex.TypeContext.STORAGE) { + srcLabel = VertexLabel.GENERAL; + tgtLabel = VertexLabel.GENERAL; } else { - if (edgeLabel.general()) { - srcLabel = VertexLabel.GENERAL; - tgtLabel = VertexLabel.GENERAL; - } else { - srcLabel = graph.vertexLabelOrNone(ownerLabelId); - tgtLabel = graph.vertexLabelOrNone(otherLabelId); - } + srcLabel = graph.vertexLabelOrNone(ownerLabelId); + tgtLabel = graph.vertexLabelOrNone(otherLabelId); } + return createEdge(ownerVertex, isOutEdge, edgeLabel, sortValues, + otherVertexId, srcLabel, tgtLabel); + } + /** Resolve no metadata, while retaining an optional supplier for later engine access. */ + public static BaseEdge createEdgeWithoutSchema(HugeGraphSupplier supplier, + BaseVertex ownerVertex, + boolean isOutEdge, + EdgeLabel edgeLabel, + String sortValues, + Id otherVertexId) { + VertexLabel source = VertexLabel.undefined(supplier, edgeLabel.sourceLabel()); + VertexLabel target = VertexLabel.undefined(supplier, edgeLabel.targetLabel()); + return createEdge(ownerVertex, isOutEdge, edgeLabel, sortValues, + otherVertexId, source, target); + } + + private static BaseEdge createEdge(BaseVertex ownerVertex, boolean isOutEdge, + EdgeLabel edgeLabel, String sortValues, Id otherVertexId, + VertexLabel srcLabel, VertexLabel tgtLabel) { VertexLabel otherVertexLabel; if (isOutEdge) { ownerVertex.correctVertexLabel(srcLabel); @@ -269,6 +323,14 @@ public static BaseEdge constructEdge(HugeGraphSupplier graph, ownerVertex.correctVertexLabel(tgtLabel); otherVertexLabel = srcLabel; } + return createEdge(ownerVertex, isOutEdge, edgeLabel, sortValues, + otherVertexId, otherVertexLabel); + } + + /** Create an edge after the caller has resolved its endpoint labels. */ + public static BaseEdge createEdge(BaseVertex ownerVertex, boolean isOutEdge, + EdgeLabel edgeLabel, String sortValues, + Id otherVertexId, VertexLabel otherVertexLabel) { BaseVertex otherVertex = new BaseVertex(otherVertexId, otherVertexLabel); ownerVertex.propLoaded(false); @@ -279,9 +341,6 @@ public static BaseEdge constructEdge(HugeGraphSupplier graph, edge.vertices(isOutEdge, ownerVertex, otherVertex); edge.assignId(); - ownerVertex.addEdge(edge); - otherVertex.addEdge(edge.switchOwner()); - return edge; } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseElement.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseElement.java index c7353d6b77..b250922d0d 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseElement.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseElement.java @@ -28,6 +28,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import org.apache.hugegraph.id.Id; @@ -41,6 +44,7 @@ import org.apache.hugegraph.type.define.HugeKeys; import org.apache.hugegraph.util.CollectionUtil; import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.InsertionOrderUtil; import org.apache.hugegraph.util.Log; import org.apache.hugegraph.util.collection.CollectionFactory; import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; @@ -49,16 +53,16 @@ import org.slf4j.Logger; -public abstract class BaseElement implements GraphType, Idfiable, Serializable { +public abstract class BaseElement implements GraphType, Idfiable, Serializable, Cloneable { private static final Logger LOG = Log.logger(BaseElement.class); - public static final MutableIntObjectMap> EMPTY_MAP = - new IntObjectHashMap<>(); + private static final MutableIntObjectMap> EMPTY_MAP = + new IntObjectHashMap>().asUnmodifiable(); - private static final int MAX_PROPERTIES = BytesBuffer.UINT16_MAX; + private static final int MAX_PROPERTIES = BytesBuffer.MAX_PROPERTIES; - MutableIntObjectMap> properties; + private MutableIntObjectMap> properties; Id id; private SchemaLabel schemaLabel; @@ -228,7 +232,15 @@ public V getPropertyValue(Id key) { } return (V) prop.value(); } + /** + * Mutable storage for codecs and owning adapters. The empty map is materialized + * per element before exposure; callers never receive the shared sentinel. + * Direct changes update this container only, without engine transaction callbacks. + */ public MutableIntObjectMap> properties() { + if (this.properties == EMPTY_MAP) { + this.properties = CollectionFactory.newIntObjectMap(); + } return this.properties; } @@ -240,13 +252,14 @@ public BaseProperty getProperty(Id key) { } private BaseProperty addProperty(PropertyKey pkey, V value, - Supplier> supplier) { + Supplier> supplier, + BiFunction> factory) { assert pkey.cardinality().multiple(); BaseProperty> property; if (this.hasProperty(pkey.id())) { property = this.getProperty(pkey.id()); } else { - property = this.newProperty(pkey, supplier.get()); + property = (BaseProperty>) factory.apply(pkey, supplier.get()); this.addProperty(property); } @@ -265,36 +278,47 @@ private BaseProperty addProperty(PropertyKey pkey, V value, values = CollectionUtil.toList(value); } } - property.value().addAll(values); + property.value().addAll(pkey.validValueOrThrow(values)); // Any better ways? return (BaseProperty) property; } public BaseProperty addProperty(PropertyKey pkey, V value) { - BaseProperty prop = null; + return this.addProperty(pkey, value, (key, val) -> this.newProperty(key, val), + prop -> {}, prop -> {}); + } + + /** Single updates notify before replacement; collection updates notify afterwards. */ + @SuppressWarnings("unchecked") + public BaseProperty addProperty( + PropertyKey pkey, V value, + BiFunction> factory, + Consumer> beforeSingle, + Consumer> afterMultiple) { + BaseProperty prop; switch (pkey.cardinality()) { case SINGLE: - prop = this.newProperty(pkey, value); + prop = (BaseProperty) factory.apply(pkey, value); + beforeSingle.accept(prop); this.addProperty(prop); break; case SET: - prop = this.addProperty(pkey, value, HashSet::new); + prop = this.addProperty(pkey, value, HashSet::new, factory); + afterMultiple.accept(prop); break; case LIST: - prop = this.addProperty(pkey, value, ArrayList::new); + prop = this.addProperty(pkey, value, ArrayList::new, factory); + afterMultiple.accept(prop); break; default: - assert false; - break; + throw new AssertionError("Unknown property cardinality: " + pkey.cardinality()); } return prop; } public BaseProperty addProperty(BaseProperty prop) { - if (this.properties == EMPTY_MAP) { - this.properties = new IntObjectHashMap<>(); // change to CollectionFactory.newIntObjectMap(); - } + this.properties(); PropertyKey pkey = prop.propertyKey(); E.checkArgument(this.properties.containsKey(intFromId(pkey.id())) || @@ -311,7 +335,11 @@ public Map> getProperties() { } public BaseProperty removeProperty(Id key) { - return this.properties.remove(intFromId(key)); + int propertyId = intFromId(key); + if (this.properties == EMPTY_MAP) { + return null; + } + return this.properties.remove(propertyId); } /* a util may be should be moved to other place */ @@ -324,7 +352,7 @@ public static int intFromId(Id id) { public abstract Object sysprop(HugeKeys key); public Map getPropertiesMap() { - Map props = new HashMap<>(); + Map props = InsertionOrderUtil.newMap(); for (IntObjectPair> e : this.properties.keyValuesView()) { props.put(IdGenerator.of(e.getOne()), e.getTwo().value()); } @@ -347,6 +375,28 @@ public int sizeOfSubProperties() { return size; } + public void copyProperties(BaseElement source) { + this.properties = source.properties == EMPTY_MAP ? EMPTY_MAP : + CollectionFactory.newIntObjectMap(source.properties); + this.propLoaded(true); + } + + public void updateDefaultValues(Function keys) { + if (this.fresh || this.defaultValueUpdated) { + return; + } + this.defaultValueUpdated = true; + for (Id id : this.schemaLabel().properties()) { + if (!this.hasProperty(id)) { + PropertyKey key = keys.apply(id); + Object value = key.defaultValue(); + if (value != null) { + this.addProperty(newProperty(key, value)); + } + } + } + } + @Override public BaseElement clone() throws CloneNotSupportedException{ return (BaseElement) super.clone(); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseProperty.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseProperty.java index d70384b631..763812eeea 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseProperty.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseProperty.java @@ -62,7 +62,7 @@ public PropertyKey propertyKey() { } public Object serialValue(boolean encodeNumber) { - return this.propertyKey.serialValue(this.value, encodeNumber); + return this.propertyKey.serialValue(this.value(), encodeNumber); } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseVertex.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseVertex.java index fe9ab832d7..6982d69a2d 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseVertex.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/BaseVertex.java @@ -21,11 +21,13 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.List; import org.apache.hugegraph.id.Id; import org.apache.hugegraph.id.SplicingIdGenerator; import org.apache.hugegraph.perf.PerfUtil; +import org.apache.hugegraph.query.ConditionQuery; import org.apache.hugegraph.struct.schema.SchemaLabel; import org.apache.hugegraph.struct.schema.VertexLabel; import org.apache.hugegraph.type.HugeType; @@ -42,6 +44,14 @@ public class BaseVertex extends BaseElement implements Cloneable { protected Collection edges; + private boolean encodeNumber = true; + private TypeContext typeContext = TypeContext.STORAGE; + + /** Classification differs for legacy storage-only and engine system labels. */ + public enum TypeContext { + STORAGE, + ENGINE + } public BaseVertex(Id id) { this.edges = EMPTY_LIST; @@ -50,11 +60,29 @@ public BaseVertex(Id id) { public BaseVertex(Id id, SchemaLabel label) { // Note: - // If vertex is OLAP Vertex, id is the id of the vertex that the olap property belongs to, not including the olap property id. + // An OLAP vertex uses the owning vertex ID without the OLAP property ID. this(id); this.schemaLabel(label); } + public BaseVertex(Id id, SchemaLabel label, TypeContext typeContext) { + this(id, label); + this.typeContext(typeContext); + } + + public TypeContext typeContext() { + return this.typeContext; + } + + public void typeContext(TypeContext typeContext) { + E.checkArgumentNotNull(typeContext, "Vertex type context can't be null"); + this.typeContext = typeContext; + } + + public void encodeNumber(boolean encodeNumber) { + this.encodeNumber = encodeNumber; + } + @Override public String name() { E.checkState(this.schemaLabel().idStrategy() == IdStrategy.PRIMARY_KEY, @@ -73,7 +101,7 @@ public String name() { E.checkState(!propValues.isEmpty(), "Primary values must not be empty " + "(has properties %s)", hasProperties()); - name = SplicingIdGenerator.concatValues(propValues); + name = ConditionQuery.concatValues(propValues); E.checkArgument(!name.isEmpty(), "The value of primary key can't be empty"); } @@ -94,18 +122,38 @@ public List primaryValues() { for (Id pk : primaryKeys) { BaseProperty property = this.getProperty(pk); E.checkState(property != null, - "The value of primary key '%s' can't be null" - /*this.graph().propertyKey(pk).name() complete log*/); - propValues.add(property.serialValue(true)); + "The value of primary key '%s' can't be null", pk); + Object value = property.serialValue(this.encodeNumber); + if ("".equals(value)) { + value = ConditionQuery.INDEX_VALUE_EMPTY; + } + propValues.add(value); } return propValues; } - public void addEdge(BaseEdge edge) { + public boolean addEdge(BaseEdge edge) { if (this.edges == EMPTY_LIST) { this.edges = CollectionFactory.newList(CollectionType.EC); } - this.edges.add(edge); + return this.edges.add(edge); + } + + public void resetEdges(boolean unique) { + this.edges = unique ? CollectionFactory.newSet(CollectionType.EC) : + CollectionFactory.newList(CollectionType.EC); + } + + public BaseEdge removeEdge(BaseEdge edge) { + Iterator iterator = this.edges.iterator(); + while (iterator.hasNext()) { + BaseEdge current = iterator.next(); + if (current.equals(edge)) { + iterator.remove(); + return current; + } + } + return null; } public void correctVertexLabel(VertexLabel correctLabel) { @@ -154,14 +202,18 @@ public boolean olap() { } public HugeType type() { - // For Vertex type, when label is task, return TASK type, convenient for getting storage table information based on type - /* Magic: ~task ~taskresult ~variables*/ - if (schemaLabel() != null && - (schemaLabel().name().equals("~task") || - schemaLabel().name().equals("~taskresult") || - schemaLabel().name().equals("~variables"))) { + if (this.schemaLabel() == null) { + return HugeType.VERTEX; + } + String label = this.schemaLabel().name(); + if ("~task".equals(label) || "~taskresult".equals(label) || + this.typeContext == TypeContext.STORAGE && "~variables".equals(label)) { return HugeType.TASK; } + if (this.typeContext == TypeContext.ENGINE && + ("~server".equals(label) || "~role_data".equals(label))) { + return HugeType.SERVER; + } return HugeType.VERTEX; } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/Index.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/Index.java index deffcde1ec..0c7c9e401d 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/Index.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/Index.java @@ -37,6 +37,7 @@ import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.DataType; import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.HashUtil; import org.apache.hugegraph.util.InsertionOrderUtil; import org.apache.hugegraph.util.NumericUtil; @@ -44,6 +45,8 @@ public class Index implements GraphType, Cloneable { + private static final int HUGE_TYPE_CODE_LENGTH = 1; + private final HugeGraphSupplier graph; private Object fieldValues; private final IndexLabel indexLabel; @@ -55,13 +58,7 @@ public class Index implements GraphType, Cloneable { private IdWithExpiredTime elementId; public Index(HugeGraphSupplier graph, IndexLabel indexLabel) { - E.checkNotNull(graph, "graph"); - E.checkNotNull(indexLabel, "label"); - E.checkNotNull(indexLabel.id(), "label id"); - this.graph = graph; - this.indexLabel = indexLabel; - this.elementIds = new LinkedHashSet<>(); - this.fieldValues = null; + this(graph, indexLabel, false); } public Index(HugeGraphSupplier graph, IndexLabel indexLabel, boolean write) { @@ -100,6 +97,10 @@ public Id id() { return formatIndexId(type(), this.indexLabelId(), this.fieldValues()); } + public Id hashId() { + return formatIndexHashId(type(), this.indexLabelId(), this.fieldValues()); + } + public Object fieldValues() { return this.fieldValues; } @@ -118,6 +119,7 @@ public IndexLabel indexLabel() { public IdWithExpiredTime elementIdWithExpiredTime() { if (this.elementIds == null) { + E.checkState(this.elementId != null, "Expect one element id, actual 0"); return this.elementId; } E.checkState(this.elementIds.size() == 1, @@ -144,8 +146,15 @@ public Set elementIds() { public Set expiredElementIds() { long now = this.graph.now(); Set expired = InsertionOrderUtil.newSet(); + if (this.elementIds == null) { + if (this.elementId != null && expired(this.elementId, now)) { + expired.add(this.elementId); + this.elementId = null; + } + return expired; + } for (IdWithExpiredTime id : this.elementIds) { - if (0L < id.expiredTime && id.expiredTime < now) { + if (expired(id, now)) { expired.add(id); } } @@ -153,6 +162,10 @@ public Set expiredElementIds() { return expired; } + private static boolean expired(IdWithExpiredTime id, long now) { + return 0L < id.expiredTime && id.expiredTime < now; + } + public void elementIds(Id elementId) { this.elementIds(elementId, 0L); } @@ -166,7 +179,11 @@ public void elementIds(Id elementId, long expiredTime) { } public void resetElementIds() { - this.elementIds = null; + if (this.elementIds == null) { + this.elementId = null; + } else { + this.elementIds = new LinkedHashSet<>(); + } } public long expiredTime() { @@ -174,17 +191,10 @@ public long expiredTime() { } public boolean hasTtl() { - if ((this.indexLabel() == IndexLabel.label(HugeType.VERTEX) || - this.indexLabel() == IndexLabel.label(HugeType.EDGE)) && - this.expiredTime() > 0) { - // LabelIndex index, if element has expiration time, then index also has TTL - return true; - } - if (this.indexLabel.system()) { return false; } - return this.indexLabel.baseElement().ttl() > 0L; + return this.indexLabel.baseLabel().ttl() > 0L; } public long ttl() { @@ -224,6 +234,14 @@ public String toString() { } + public static Id formatIndexHashId(HugeType type, Id indexLabel, + Object fieldValues) { + E.checkState(!type.isRangeIndex(), + "RangeIndex can't return a hash id"); + String value = fieldValues == null ? "" : fieldValues.toString(); + return formatIndexId(type, indexLabel, HashUtil.hash(value)); + } + public static Id formatIndexId(HugeType type, Id indexLabelId, Object fieldValues) { if (type.isStringIndex()) { @@ -239,12 +257,11 @@ public static Id formatIndexId(HugeType type, Id indexLabelId, */ String strIndexLabelId = IdGenerator.asStoredString(indexLabelId); // Add id prefix according to type - return SplicingIdGenerator.splicing(type.string(), strIndexLabelId, value); + return SplicingIdGenerator.splicing(type.string(), strIndexLabelId, value); } else { assert type.isRangeIndex(); int length = type.isRange4Index() ? 4 : 8; - // 1 is table type, 4 is labelId, length is value - BytesBuffer buffer = BytesBuffer.allocate(1 + 4 + length); + BytesBuffer buffer = BytesBuffer.allocate(HUGE_TYPE_CODE_LENGTH + 4 + length); // Add table type id buffer.write(type.code()); @@ -276,9 +293,7 @@ public static Index parseIndexId(HugeGraphSupplier graph, HugeType type, final int labelLength = 4; E.checkState(id.length > labelLength, "Invalid range index id"); BytesBuffer buffer = BytesBuffer.wrap(id); - // Read the first byte representing the table type - final int hugeTypeCodeLength = 1; - byte[] read = buffer.read(hugeTypeCodeLength); + buffer.read(HUGE_TYPE_CODE_LENGTH); Id label = IdGenerator.of(buffer.readInt()); indexLabel = IndexLabel.label(graph, label); @@ -289,7 +304,8 @@ public static Index parseIndexId(HugeGraphSupplier graph, HugeType type, "Invalid range index field type"); Class clazz = dataType.isNumber() ? dataType.clazz() : DataType.LONG.clazz(); - values = bytes2number(buffer.read(id.length - labelLength - hugeTypeCodeLength), clazz); + values = bytes2number(buffer.read(id.length - labelLength - HUGE_TYPE_CODE_LENGTH), + clazz); } Index index = new Index(graph, indexLabel); index.fieldValues(values); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/builder/IndexBuilder.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/builder/IndexBuilder.java index cc1483f39e..0929a3b2f0 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/builder/IndexBuilder.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/structure/builder/IndexBuilder.java @@ -22,7 +22,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; import org.apache.commons.lang3.StringUtils; import org.apache.hugegraph.HugeGraphSupplier; @@ -41,19 +44,26 @@ import org.apache.hugegraph.structure.Index; import org.apache.hugegraph.util.E; import org.apache.hugegraph.util.Log; +import org.apache.hugegraph.util.InsertionOrderUtil; import org.apache.hugegraph.util.NumericUtil; import org.slf4j.Logger; +import com.google.common.collect.ImmutableSet; + public class IndexBuilder { private static final Logger LOG = Log.logger(IndexBuilder.class); private final HugeGraphSupplier graph; private final Analyzer textAnalyzer; + public static final String START_SYMBOL = "("; + public static final String END_SYMBOL = ")"; + public static final String WORD_DELIMITER = "|"; + - public static final String INDEX_SYM_NULL = "\u0001"; - public static final String INDEX_SYM_EMPTY = "\u0002"; - public static final char INDEX_SYM_MAX = '\u0003'; + public static final String INDEX_SYM_NULL = ConditionQuery.INDEX_SYM_NULL; + public static final String INDEX_SYM_EMPTY = ConditionQuery.INDEX_SYM_EMPTY; + public static final char INDEX_SYM_MAX = ConditionQuery.INDEX_SYM_MAX; private static final String TEXT_ANALYZER = "search.text_analyzer"; private static final String TEXT_ANALYZER_MODE = @@ -63,18 +73,21 @@ public class IndexBuilder { private static final String DEFAULT_TEXT_ANALYZER_MODE = "smart"; public IndexBuilder(HugeGraphSupplier graph) { - this.graph = graph; + this(graph, createAnalyzer(graph)); + } - String name = graph.configuration().get(String.class, TEXT_ANALYZER); - String mode = graph.configuration().get(String.class, - TEXT_ANALYZER_MODE); + public IndexBuilder(HugeGraphSupplier graph, Analyzer textAnalyzer) { + this.graph = Objects.requireNonNull(graph, "graph"); + this.textAnalyzer = Objects.requireNonNull(textAnalyzer, "textAnalyzer"); + } + private static Analyzer createAnalyzer(HugeGraphSupplier graph) { + String name = graph.configuration().get(String.class, TEXT_ANALYZER); + String mode = graph.configuration().get(String.class, TEXT_ANALYZER_MODE); name = name == null ? DEFAULT_TEXT_ANALYZER : name; mode = mode == null ? DEFAULT_TEXT_ANALYZER_MODE : mode; - - LOG.debug("Loading text analyzer '{}' with mode '{}' for graph '{}'", - name, mode, graph.name()); - this.textAnalyzer = AnalyzerFactory.analyzer(name, mode); + LOG.debug("Loading text analyzer '{}' with mode '{}' for graph '{}'", name, mode, graph.name()); + return AnalyzerFactory.analyzer(name, mode); } public List buildLabelIndex(BaseElement element) { @@ -107,19 +120,17 @@ public List buildLabelIndex(BaseElement element) { return indexList; } - public List buildVertexOlapIndex(BaseVertex vertex) { - - List indexs = new ArrayList<>(); - - Id pkId = vertex.getProperties().keySet().iterator().next(); - Collection indexLabels = graph.indexLabels(); - for (IndexLabel il : indexLabels) { - if (il.indexFields().contains(pkId)) { - indexs.addAll(this.buildIndex(vertex, il)); + public static void forEachOlapIndexLabelId(BaseVertex vertex, Iterable candidates, + Consumer sink) { + int properties = vertex.sizeOfProperties(); + E.checkArgument(properties == 1, + "Expect only 1 property for olap vertex, but got %s", properties); + Id propertyId = vertex.properties().values().iterator().next().propertyKey().id(); + for (IndexLabel label : candidates) { + if (label.indexFields().contains(propertyId)) { + sink.accept(label.id()); } } - - return indexs; } public List buildVertexIndex(BaseVertex vertex) { @@ -131,9 +142,8 @@ public List buildVertexIndex(BaseVertex vertex) { indexs.addAll(this.buildLabelIndex(vertex)); } - for (Id il : label.indexLabels()) { - indexs.addAll(this.buildIndex(vertex, graph.indexLabel(il))); - } + forEachIndexLabelId(vertex, this.graph::edgeLabel, + id -> this.forEachIndex(vertex, this.graph.indexLabel(id), indexs::add)); return indexs; } @@ -148,13 +158,28 @@ public List buildEdgeIndex(BaseEdge edge) { } - for (Id il : label.indexLabels()) { - indexs.addAll(this.buildIndex(edge, graph.indexLabel(il))); - } + forEachIndexLabelId(edge, this.graph::edgeLabel, + id -> this.forEachIndex(edge, this.graph.indexLabel(id), indexs::add)); return indexs; } + public static void forEachIndexLabelId(BaseElement element, Function edgeLabelLookup, + Consumer sink) { + for (Id id : element.schemaLabel().indexLabels()) { + sink.accept(id); + } + if (element instanceof BaseEdge) { + EdgeLabel label = (EdgeLabel) element.schemaLabel(); + if (label.hasFather()) { + // Preserve child-first order and repeated IDs from the engine's existing loops. + for (Id id : edgeLabelLookup.apply(label.fatherId()).indexLabels()) { + sink.accept(id); + } + } + } + } + /** * Build index(user properties) of vertex or edge * Notice: This method does not use unique index validation to check if the current element already exists @@ -163,10 +188,14 @@ public List buildEdgeIndex(BaseEdge edge) { * @param element the properties owner */ public List buildIndex(BaseElement element, IndexLabel indexLabel) { - E.checkArgument(indexLabel != null, - "Not exist index label with id '%s'", indexLabel.id()); + List indexes = new ArrayList<>(); + this.forEachIndex(element, indexLabel, indexes::add); + return indexes; + } - List indexs = new ArrayList<>(); + public void forEachIndex(BaseElement element, IndexLabel indexLabel, Consumer sink) { + E.checkArgumentNotNull(indexLabel, "Index label cannot be null"); + Objects.requireNonNull(sink, "sink"); // Collect property values of index fields List allPropValues = new ArrayList<>(); @@ -181,18 +210,15 @@ public List buildIndex(BaseElement element, IndexLabel indexLabel) { if (firstNullField == fieldsNum) { firstNullField = allPropValues.size(); } - allPropValues.add(INDEX_SYM_NULL); + allPropValues.add(ConditionQuery.INDEX_VALUE_NULL); } else { - E.checkArgument(!INDEX_SYM_NULL.equals(property.value()), - "Illegal value of index property: '%s'", - INDEX_SYM_NULL); allPropValues.add(property.value()); } } if (firstNullField == 0 && !indexLabel.indexType().isUnique()) { // The property value of first index field is null - return indexs; + return; } // Not build index for record with nullable field (except unique index) List propValues = allPropValues.subList(0, firstNullField); @@ -209,7 +235,7 @@ public List buildIndex(BaseElement element, IndexLabel indexLabel) { E.checkState(propValues.size() == 1, "Expect only one property in range index"); Object value = NumericUtil.convertToNumber(propValues.get(0)); - indexs.add(this.buildIndex(indexLabel, value, element.id(), + sink.accept(this.buildIndex(indexLabel, value, element.id(), expiredTime)); break; case SEARCH: @@ -219,7 +245,7 @@ public List buildIndex(BaseElement element, IndexLabel indexLabel) { Set words = this.segmentWords(propertyValueToString(value)); for (String word : words) { - indexs.add(this.buildIndex(indexLabel, word, element.id(), + sink.accept(this.buildIndex(indexLabel, word, element.id(), expiredTime)); } break; @@ -232,10 +258,9 @@ public List buildIndex(BaseElement element, IndexLabel indexLabel) { */ for (Object propValue : (Collection) propValues.get(0)) { - value = ConditionQuery.concatValuesLimitLength( + value = ConditionQuery.concatValues( propValue); - value = escapeIndexValueIfNeeded((String) value); - indexs.add(this.buildIndex(indexLabel, value, + sink.accept(this.buildIndex(indexLabel, value, element.id(), expiredTime)); } @@ -243,25 +268,23 @@ public List buildIndex(BaseElement element, IndexLabel indexLabel) { for (int i = 0, n = propValues.size(); i < n; i++) { List prefixValues = propValues.subList(0, i + 1); - value = ConditionQuery.concatValuesLimitLength( + value = ConditionQuery.concatValues( prefixValues); - value = escapeIndexValueIfNeeded((String) value); - indexs.add(this.buildIndex(indexLabel, value, + sink.accept(this.buildIndex(indexLabel, value, element.id(), expiredTime)); } } break; case SHARD: - value = ConditionQuery.concatValuesLimitLength(propValues); - value = escapeIndexValueIfNeeded((String) value); - indexs.add(this.buildIndex(indexLabel, value, element.id(), + value = ConditionQuery.concatValues(propValues); + sink.accept(this.buildIndex(indexLabel, value, element.id(), expiredTime)); break; case UNIQUE: - value = ConditionQuery.concatValuesLimitLength(allPropValues); + value = ConditionQuery.concatValues(allPropValues); assert !"".equals(value); - indexs.add(this.buildIndex(indexLabel, value, element.id(), + sink.accept(this.buildIndex(indexLabel, value, element.id(), expiredTime)); break; default: @@ -269,7 +292,6 @@ public List buildIndex(BaseElement element, IndexLabel indexLabel) { "Unknown index type '%s'", indexLabel.indexType())); } - return indexs; } private Index buildIndex(IndexLabel indexLabel, Object propValue, @@ -282,26 +304,6 @@ private Index buildIndex(IndexLabel indexLabel, Object propValue, } - private static String escapeIndexValueIfNeeded(String value) { - for (int i = 0; i < value.length(); i++) { - char ch = value.charAt(i); - if (ch <= INDEX_SYM_MAX) { - /* - * Escape symbols can't be used due to impossible to parse, - * and treat it as illegal value for the origin text property - */ - E.checkArgument(false, "Illegal char '\\u000%s' " + - "in index property: '%s'", (int) ch, - value); - } - } - if (value.isEmpty()) { - // Escape empty String to INDEX_SYM_EMPTY (char `\u0002`) - value = INDEX_SYM_EMPTY; - } - return value; - } - private static boolean hasNullableProp(BaseElement element, Id key) { return element.schemaLabel().nullableKeys().contains(key); } @@ -311,17 +313,20 @@ private static boolean isCollectionIndex(List propValues) { propValues.get(0) instanceof Collection; } - private Set segmentWords(String text) { - return this.textAnalyzer.segment(text); + public Set segmentWords(String text) { + if (text.startsWith(START_SYMBOL) && text.endsWith(END_SYMBOL)) { + String words = text.substring(1, text.length() - 1); + return words.contains(WORD_DELIMITER) ? + ImmutableSet.copyOf(StringUtils.split(words, WORD_DELIMITER)) : ImmutableSet.of(words); + } + Set segments = InsertionOrderUtil.newSet(); + segments.addAll(this.textAnalyzer.segment(text)); + segments.add(text); + segments.removeAll(ConditionQuery.IGNORE_SYM_SET); + return segments; } - private static String propertyValueToString(Object value) { - /* - * Join collection items with white space if the value is Collection, - * or else keep the origin value. - */ - return value instanceof Collection ? - StringUtils.join(((Collection) value).toArray(), " ") : - value.toString(); + public static String propertyValueToString(Object value) { + return value instanceof Collection ? StringUtils.join((Iterable) value, " ") : value.toString(); } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/HugeType.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/HugeType.java index 2fac93100a..122036ae38 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/HugeType.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/HugeType.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type; @@ -123,9 +121,8 @@ public boolean isGraph() { } public boolean isVertex() { - // Consider task vertex variable as the same, all used to store HugeVertex structure - return this == HugeType.VERTEX || this == HugeType.TASK || - this == HugeType.VARIABLE || this == HugeType.SERVER; + return this == HugeType.VERTEX || this == HugeType.TASK || this == HugeType.SERVER || + this == HugeType.VARIABLE; } public boolean isEdge() { diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/Idfiable.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/Idfiable.java index c5a58c0eb1..59b8f1e3a3 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/Idfiable.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/Idfiable.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type; @@ -23,5 +21,5 @@ public interface Idfiable { - public Id id(); + Id id(); } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Action.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Action.java index 042594c224..9561d52181 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Action.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Action.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/AggregateType.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/AggregateType.java index e949d4af14..31c0f6212d 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/AggregateType.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/AggregateType.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Cardinality.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Cardinality.java index 9f34a96dee..cf10a5acf7 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Cardinality.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Cardinality.java @@ -14,8 +14,6 @@ package org.apache.hugegraph.type.define; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - /** * The cardinality of the values associated with given key for a particular element. * @@ -39,8 +37,8 @@ public enum Cardinality implements SerialEnum { */ SET(3, "set"); - private byte code = 0; - private String name = null; + private final byte code; + private final String name; static { SerialEnum.register(Cardinality.class); @@ -69,17 +67,4 @@ public boolean multiple() { return this == LIST || this == SET; } - public static Cardinality convert(VertexProperty.Cardinality cardinality) { - switch (cardinality) { - case single: - return SINGLE; - case list: - return LIST; - case set: - return SET; - default: - throw new AssertionError(String.format("Unrecognized cardinality: '%s'", - cardinality)); - } - } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/CollectionType.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/CollectionType.java index e8ff98ec95..e8a4cd3547 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/CollectionType.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/CollectionType.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; @@ -62,7 +60,7 @@ public static CollectionType fromCode(byte code) { return FU; default: throw new AssertionError( - "Unsupported collection code: " + code); + "Unsupported collection code: " + code); } } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Frequency.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Frequency.java index 4ebe24867a..3fd1c82332 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Frequency.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/Frequency.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java index c396e429c5..0e3536b011 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; @@ -53,7 +51,6 @@ public enum HugeKeys { EDGELABEL_TYPE(87, "edgelabel_type"), PARENT_LABEL(89, "parent_label"), - /* Column names of schema type (PropertyKey) */ DATA_TYPE(120, "data_type"), CARDINALITY(121, "cardinality"), @@ -82,11 +79,10 @@ public enum HugeKeys { SORT_VALUES(206, "sort_values"), PRIMARY_VALUES(207, "primary_values"), EXPIRED_TIME(208, "expired_time"), - SUB_LABEL(211,"sub_label"), + SUB_LABEL(211, "sub_label"), PROPERTY_TYPE(249, "property_type"), - AGGREGATE_PROPERTIES(250, "aggregate_properties"), - ; + AGGREGATE_PROPERTIES(250, "aggregate_properties"); public static final long NORMAL_PROPERTY_ID = 0L; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java index 4149c8db91..da9f51313c 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IdStrategy.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IndexType.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IndexType.java index 77e59932e7..019ac98df9 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IndexType.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/IndexType.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java index 337c981a76..3cb59b0450 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/SerialEnum.java @@ -1,65 +1,65 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; -import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.exception.BackendException; import org.apache.hugegraph.type.HugeType; - import org.apache.hugegraph.util.CollectionUtil; import org.apache.hugegraph.util.E; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; public interface SerialEnum { - public byte code(); - -// static Table, Byte, SerialEnum> table = HashBasedTable.create(); + byte code(); - static Map>table =new ConcurrentHashMap<>(); + Table, Byte, SerialEnum> TABLE = HashBasedTable.create(); - public static void register(Class clazz) { + static void register(Class clazz) { Object enums; try { enums = clazz.getMethod("values").invoke(null); } catch (Exception e) { - throw new HugeException("Exception in backend", e); + throw new BackendException(e); } - ConcurrentHashMap map=new ConcurrentHashMap(); - for (SerialEnum e : CollectionUtil.toList(enums)) { - map.put(e.code(), e); + // Resolve enum initialization before locking: class initializers register here too. + synchronized (TABLE) { + for (SerialEnum e : CollectionUtil.toList(enums)) { + TABLE.put(clazz, e.code(), e); + } } - table.put(clazz,map); } - - public static T fromCode(Class clazz, byte code) { - Map clazzMap=table.get(clazz); - if (clazzMap == null) { - SerialEnum.register(clazz); - clazzMap=table.get(clazz); + static T fromCode(Class clazz, byte code) { + boolean registered; + synchronized (TABLE) { + registered = TABLE.containsRow(clazz); + } + if (!registered) { + register(clazz); + } + T value; + synchronized (TABLE) { + @SuppressWarnings("unchecked") + T entry = (T) TABLE.get(clazz, code); + value = entry; } - E.checkArgument(clazzMap != null, "Can't get class registery for %s", - clazz.getSimpleName()); - T value = (T) clazzMap.get(code); if (value == null) { E.checkArgument(false, "Can't construct %s from code %s", clazz.getSimpleName(), code); @@ -67,7 +67,7 @@ public static T fromCode(Class clazz, byte code) { return value; } - public static void registerInternalEnums() { + static void registerInternalEnums() { SerialEnum.register(Action.class); SerialEnum.register(AggregateType.class); SerialEnum.register(Cardinality.class); @@ -78,6 +78,5 @@ public static void registerInternalEnums() { SerialEnum.register(IdStrategy.class); SerialEnum.register(IndexType.class); SerialEnum.register(SchemaStatus.class); -// SerialEnum.register(HugePermission.class); } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/WriteType.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/WriteType.java index 538b5bc40b..ea1018eabd 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/WriteType.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/type/define/WriteType.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.type.define; @@ -33,8 +31,8 @@ public enum WriteType implements SerialEnum { // OLAP property key with range index OLAP_RANGE(4, "olap_range"); - private final byte code; - private final String name; + private byte code = 0; + private String name = null; static { SerialEnum.register(WriteType.class); diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/Blob.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/Blob.java index 03d82e916e..5b5d8ec6ad 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/Blob.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/Blob.java @@ -1,29 +1,24 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.util; import java.util.Arrays; -import org.apache.hugegraph.util.Bytes; -import org.apache.hugegraph.util.E; - public class Blob implements Comparable { public static final Blob EMPTY = new Blob(new byte[0]); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/KryoUtil.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java similarity index 83% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/KryoUtil.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java index ce789c6d8d..02e6b7a2d3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/KryoUtil.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java @@ -21,11 +21,13 @@ import java.io.IOException; import java.util.UUID; -import org.apache.hugegraph.backend.BackendException; +import org.apache.hugegraph.exception.BackendException; import org.apache.tinkerpop.shaded.kryo.Kryo; import org.apache.tinkerpop.shaded.kryo.Serializer; import org.apache.tinkerpop.shaded.kryo.io.Input; import org.apache.tinkerpop.shaded.kryo.io.Output; +import org.apache.tinkerpop.shaded.kryo.util.DefaultClassResolver; +import org.apache.tinkerpop.shaded.kryo.util.MapReferenceResolver; public final class KryoUtil { @@ -37,7 +39,7 @@ public static Kryo kryo() { return kryo; } - kryo = new Kryo(); + kryo = new Kryo(new LegacyClassResolver(), new MapReferenceResolver()); registerSerializers(kryo); KRYOS.set(kryo); return kryo; @@ -78,6 +80,16 @@ public static T fromKryoWithType(byte[] value) { return (T) kryo().readClassAndObject(new Input(value)); } + /** Resolve relocated names only when Kryo decodes a class descriptor. */ + private static class LegacyClassResolver extends DefaultClassResolver { + + @Override + protected Class getTypeByName(String name) { + Class type = LegacyClassNames.lookup(name); + return type != null ? type : super.getTypeByName(name); + } + } + private static void registerSerializers(Kryo kryo) { kryo.addDefaultSerializer(UUID.class, new Serializer() { diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LZ4Util.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LZ4Util.java index 98f23b9b29..253d813953 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LZ4Util.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LZ4Util.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.util; @@ -39,25 +37,20 @@ public static BytesBuffer compress(byte[] bytes, int blockSize) { return compress(bytes, blockSize, DEFAULT_BUFFER_RATIO); } - public static BytesBuffer compress(byte[] bytes, int blockSize, - float bufferRatio) { + public static BytesBuffer compress(byte[] bytes, int blockSize, float bufferRatio) { float ratio = bufferRatio <= 0.0F ? DEFAULT_BUFFER_RATIO : bufferRatio; LZ4Factory factory = LZ4Factory.fastestInstance(); LZ4Compressor compressor = factory.fastCompressor(); int initBufferSize = Math.round(bytes.length / ratio); BytesBuffer buf = new BytesBuffer(initBufferSize); - LZ4BlockOutputStream lz4Output = new LZ4BlockOutputStream( - buf, blockSize, compressor); + LZ4BlockOutputStream lz4Output = new LZ4BlockOutputStream(buf, blockSize, compressor); try { lz4Output.write(bytes); lz4Output.close(); } catch (IOException e) { throw new BackendException("Failed to compress", e); } - /* - * If need to perform reading outside the method, - * remember to call forReadWritten() - */ + // If we need to perform reading outside the method, remember to call forReadWritten() return buf; } @@ -65,17 +58,15 @@ public static BytesBuffer decompress(byte[] bytes, int blockSize) { return decompress(bytes, blockSize, DEFAULT_BUFFER_RATIO); } - public static BytesBuffer decompress(byte[] bytes, int blockSize, - float bufferRatio) { + public static BytesBuffer decompress(byte[] bytes, int blockSize, float bufferRatio) { float ratio = bufferRatio <= 0.0F ? DEFAULT_BUFFER_RATIO : bufferRatio; LZ4Factory factory = LZ4Factory.fastestInstance(); LZ4FastDecompressor decompressor = factory.fastDecompressor(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); int initBufferSize = Math.min(Math.round(bytes.length * ratio), - BytesBuffer.MAX_BUFFER_CAPACITY); + BytesBuffer.maxBufferCapacity()); BytesBuffer buf = new BytesBuffer(initBufferSize); - LZ4BlockInputStream lzInput = new LZ4BlockInputStream(bais, - decompressor); + LZ4BlockInputStream lzInput = new LZ4BlockInputStream(bais, decompressor); int count; byte[] buffer = new byte[blockSize]; try { @@ -86,10 +77,7 @@ public static BytesBuffer decompress(byte[] bytes, int blockSize, } catch (IOException e) { throw new BackendException("Failed to decompress", e); } - /* - * If need to perform reading outside the method, - * remember to call forReadWritten() - */ + // If we need to perform reading outside the method, remember to call forReadWritten() return buf; } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LegacyClassNames.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LegacyClassNames.java new file mode 100644 index 0000000000..edb791e519 --- /dev/null +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/LegacyClassNames.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.util; + +import java.lang.reflect.Array; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.backend.BinaryId; +import org.apache.hugegraph.backend.Shard; +import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.exception.HugeException; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdUtil; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.Aggregate; +import org.apache.hugegraph.query.BatchConditionQuery; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.IdPrefixQuery; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.query.IdRangeQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.query.serializer.AbstractSerializerAdapter; +import org.apache.hugegraph.query.serializer.QueryAdapter; +import org.apache.hugegraph.query.serializer.QueryIdAdapter; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.SchemaLabel; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.builder.SchemaBuilder; +import org.apache.hugegraph.type.GraphType; +import org.apache.hugegraph.type.Indexfiable; +import org.apache.hugegraph.type.Namifiable; +import org.apache.hugegraph.type.Propfiable; +import org.apache.hugegraph.type.Typifiable; + +/** Exact relocated class descriptors accepted by legacy JSON and Kryo decoders. */ +public final class LegacyClassNames { + + private static final Map> LEGACY_CLASSES = legacyClasses(); + + private LegacyClassNames() { + } + + /** Return an exact migrated type, or null so the caller retains its normal loader. */ + public static Class lookup(String name) { + Class type = LEGACY_CLASSES.get(name); + if (type != null) { + return type; + } + // Object arrays use JVM descriptors; keep dimensions and remap + // only an exact, known component name. Primitive arrays use the + // unchanged default resolver. + int dimensions = 0; + while (dimensions < name.length() && name.charAt(dimensions) == '[') { + dimensions++; + if (dimensions > 255) { + return null; + } + } + if (dimensions > 0 && dimensions < name.length() && + name.charAt(dimensions) == 'L' && name.endsWith(";")) { + type = LEGACY_CLASSES.get(name.substring(dimensions + 1, name.length() - 1)); + if (type != null) { + return Array.newInstance(type, new int[dimensions]).getClass(); + } + } + return null; + } + + private static Class declaredClass(Class owner, String name) { + for (Class type : owner.getDeclaredClasses()) { + if (type.getSimpleName().equals(name)) { + return type; + } + } + throw new IllegalStateException("Missing legacy target: " + owner.getName() + "$" + name); + } + + private static Map> legacyClasses() { + Map> classes = new HashMap<>(); + classes.put("org.apache.hugegraph.backend.id.Id", Id.class); + classes.put("org.apache.hugegraph.backend.id.IdGenerator", IdGenerator.class); + classes.put("org.apache.hugegraph.backend.id.IdUtil", IdUtil.class); + classes.put("org.apache.hugegraph.backend.id.SplicingIdGenerator", SplicingIdGenerator.class); + classes.put("org.apache.hugegraph.backend.serializer.BytesBuffer", BytesBuffer.class); + classes.put("org.apache.hugegraph.type.Typeable", Typifiable.class); + classes.put("org.apache.hugegraph.type.Nameable", Namifiable.class); + classes.put("org.apache.hugegraph.type.Propertiable", Propfiable.class); + classes.put("org.apache.hugegraph.type.Indexable", Indexfiable.class); + classes.put("org.apache.hugegraph.backend.id.Id$IdType", Id.IdType.class); + classes.put("org.apache.hugegraph.backend.id.IdGenerator$StringId", IdGenerator.StringId.class); + classes.put("org.apache.hugegraph.backend.id.IdGenerator$LongId", IdGenerator.LongId.class); + classes.put("org.apache.hugegraph.backend.id.IdGenerator$UuidId", IdGenerator.UuidId.class); + classes.put("org.apache.hugegraph.backend.id.IdGenerator$ObjectId", IdGenerator.ObjectId.class); + classes.put("org.apache.hugegraph.backend.id.EdgeId", EdgeId.class); + classes.put("org.apache.hugegraph.backend.serializer.BinaryBackendEntry$BinaryId", BinaryId.class); + classes.put("org.apache.hugegraph.backend.store.BackendEntry$BackendColumn", BackendColumn.class); + classes.put("org.apache.hugegraph.backend.store.Shard", Shard.class); + classes.put("org.apache.hugegraph.HugeException", HugeException.class); + classes.put("org.apache.hugegraph.backend.BackendException", BackendException.class); + classes.put("org.apache.hugegraph.structure.GraphType", GraphType.class); + classes.put("org.apache.hugegraph.schema.SchemaElement", SchemaElement.class); + classes.put("org.apache.hugegraph.schema.SchemaLabel", SchemaLabel.class); + classes.put("org.apache.hugegraph.schema.PropertyKey", PropertyKey.class); + classes.put("org.apache.hugegraph.schema.VertexLabel", VertexLabel.class); + classes.put("org.apache.hugegraph.schema.EdgeLabel", EdgeLabel.class); + classes.put("org.apache.hugegraph.schema.IndexLabel", IndexLabel.class); + classes.put("org.apache.hugegraph.schema.Userdata", Userdata.class); + classes.put("org.apache.hugegraph.schema.SchemaElement$TaskWithSchema", SchemaElement.TaskWithSchema.class); + classes.put("org.apache.hugegraph.schema.SchemaElement$P", SchemaElement.P.class); + classes.put("org.apache.hugegraph.schema.PropertyKey$P", declaredClass(PropertyKey.class, "P")); + classes.put("org.apache.hugegraph.schema.VertexLabel$P", declaredClass(VertexLabel.class, "P")); + classes.put("org.apache.hugegraph.schema.EdgeLabel$P", declaredClass(EdgeLabel.class, "P")); + classes.put("org.apache.hugegraph.schema.IndexLabel$P", declaredClass(IndexLabel.class, "P")); + classes.put("org.apache.hugegraph.schema.PropertyKey$Builder", PropertyKey.Builder.class); + classes.put("org.apache.hugegraph.schema.VertexLabel$Builder", VertexLabel.Builder.class); + classes.put("org.apache.hugegraph.schema.EdgeLabel$Builder", EdgeLabel.Builder.class); + classes.put("org.apache.hugegraph.schema.IndexLabel$Builder", IndexLabel.Builder.class); + classes.put("org.apache.hugegraph.structure.HugeIndex", Index.class); + classes.put("org.apache.hugegraph.structure.HugeIndex$IdWithExpiredTime", Index.IdWithExpiredTime.class); + classes.put("org.apache.hugegraph.schema.builder.SchemaBuilder", SchemaBuilder.class); + classes.put("org.apache.hugegraph.backend.query.serializer.AbstractSerializerAdapter", + AbstractSerializerAdapter.class); + classes.put("org.apache.hugegraph.backend.query.serializer.QueryAdapter", QueryAdapter.class); + classes.put("org.apache.hugegraph.backend.query.serializer.QueryIdAdapter", QueryIdAdapter.class); + classes.put("org.apache.hugegraph.backend.query.Query", Query.class); + classes.put("org.apache.hugegraph.backend.query.Query$Order", Query.Order.class); + classes.put("org.apache.hugegraph.backend.query.Query$OrderType", Query.OrderType.class); + classes.put("org.apache.hugegraph.backend.query.IdQuery", IdQuery.class); + classes.put("org.apache.hugegraph.backend.query.IdQuery$OneIdQuery", IdQuery.OneIdQuery.class); + classes.put("org.apache.hugegraph.backend.query.IdPrefixQuery", IdPrefixQuery.class); + classes.put("org.apache.hugegraph.backend.query.IdRangeQuery", IdRangeQuery.class); + classes.put("org.apache.hugegraph.backend.query.ConditionQuery", ConditionQuery.class); + classes.put("org.apache.hugegraph.backend.query.ConditionQuery$OptimizedType", + ConditionQuery.OptimizedType.class); + classes.put("org.apache.hugegraph.backend.query.ConditionQuery$Element2IndexValueMap", + ConditionQuery.Element2IndexValueMap.class); + classes.put("org.apache.hugegraph.backend.query.ConditionQuery$LeftIndex", ConditionQuery.LeftIndex.class); + classes.put("org.apache.hugegraph.backend.query.BatchConditionQuery", BatchConditionQuery.class); + classes.put("org.apache.hugegraph.backend.query.Aggregate", Aggregate.class); + classes.put("org.apache.hugegraph.backend.query.Aggregate$AggregateFunc", Aggregate.AggregateFunc.class); + classes.put("org.apache.hugegraph.backend.query.Condition", Condition.class); + classes.put("org.apache.hugegraph.backend.query.Condition$ConditionType", Condition.ConditionType.class); + classes.put("org.apache.hugegraph.backend.query.Condition$RelationType", Condition.RelationType.class); + classes.put("org.apache.hugegraph.backend.query.Condition$BinCondition", Condition.BinCondition.class); + classes.put("org.apache.hugegraph.backend.query.Condition$And", Condition.And.class); + classes.put("org.apache.hugegraph.backend.query.Condition$Or", Condition.Or.class); + classes.put("org.apache.hugegraph.backend.query.Condition$Not", Condition.Not.class); + classes.put("org.apache.hugegraph.backend.query.Condition$Relation", Condition.Relation.class); + classes.put("org.apache.hugegraph.backend.query.Condition$SyspropRelation", Condition.SyspropRelation.class); + classes.put("org.apache.hugegraph.backend.query.Condition$FlattenSyspropRelation", + Condition.FlattenSyspropRelation.class); + classes.put("org.apache.hugegraph.backend.query.Condition$UserpropRelation", Condition.UserpropRelation.class); + classes.put("org.apache.hugegraph.backend.query.Condition$RangeConditions", Condition.RangeConditions.class); + return Collections.unmodifiableMap(classes); + } + +} diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java index f4690d430d..f046b3ac0b 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java @@ -1,21 +1,3 @@ -/* - * Copyright 2017 HugeGraph Authors - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ // Copyright 2017 JanusGraph Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,18 +14,16 @@ package org.apache.hugegraph.util; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.UUID; -import org.apache.hugegraph.util.Bytes; -import org.apache.hugegraph.util.E; -import org.mindrot.jbcrypt.BCrypt; - import org.apache.hugegraph.exception.HugeException; import org.apache.hugegraph.serializer.BytesBuffer; +import org.mindrot.jbcrypt.BCrypt; + import com.google.common.base.CharMatcher; /** @@ -54,8 +34,8 @@ public final class StringEncoding { private static final MessageDigest DIGEST; private static final byte[] BYTES_EMPTY = new byte[0]; + private static final String STRING_EMPTY = ""; private static final int BLOCK_SIZE = 4096; - private static final int BCRYPT_WORK_FACTOR = 10; static { @@ -70,7 +50,7 @@ public final class StringEncoding { private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder(); private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder(); - // Similar to {@link StringSerializer} + /** Similar to {@link StringSerializer} */ public static int writeAsciiString(byte[] array, int offset, String value) { E.checkArgument(CharMatcher.ascii().matchesAllOf(value), "'%s' must be ASCII string", value); @@ -86,7 +66,8 @@ public static int writeAsciiString(byte[] array, int offset, String value) { assert c <= 127; byte b = (byte) c; if (++i == len) { - b |= 0x80; // End marker + // End marker + b |= 0x80; } array[offset++] = b; } while (i < len); @@ -96,7 +77,7 @@ public static int writeAsciiString(byte[] array, int offset, String value) { public static String readAsciiString(byte[] array, int offset) { StringBuilder sb = new StringBuilder(); - int c = 0; + int c; do { c = 0xFF & array[offset++]; if (c != 0x80) { @@ -113,27 +94,21 @@ public static int getAsciiByteLength(String value) { } public static byte[] encode(String value) { - try { - return value.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new HugeException("Failed to encode string", e); - } + return value.getBytes(StandardCharsets.UTF_8); } public static String decode(byte[] bytes) { - try { - return new String(bytes, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new HugeException("Failed to decode string", e); + if (bytes.length == 0) { + return STRING_EMPTY; } + return new String(bytes, StandardCharsets.UTF_8); } public static String decode(byte[] bytes, int offset, int length) { - try { - return new String(bytes, offset, length, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new HugeException("Failed to decode string", e); + if (length == 0) { + return STRING_EMPTY; } + return new String(bytes, offset, length, StandardCharsets.UTF_8); } public static String encodeBase64(byte[] bytes) { @@ -152,8 +127,7 @@ public static byte[] compress(String value) { } public static byte[] compress(String value, float bufferRatio) { - BytesBuffer buf = LZ4Util.compress(encode(value), BLOCK_SIZE, - bufferRatio); + BytesBuffer buf = LZ4Util.compress(encode(value), BLOCK_SIZE, bufferRatio); return buf.bytes(); } @@ -172,8 +146,7 @@ public static String hashPassword(String password) { return BCrypt.hashpw(password, BCrypt.gensalt(BCRYPT_WORK_FACTOR)); } - public static boolean checkPassword(String candidatePassword, - String dbPassword) { + public static boolean checkPassword(String candidatePassword, String dbPassword) { return BCrypt.checkpw(candidatePassword, dbPassword); } @@ -194,8 +167,7 @@ public static UUID uuid(String value) { return UUID.fromString(value); } // UUID represented by hex string - E.checkArgument(value.length() == 32, - "Invalid UUID string: %s", value); + E.checkArgument(value.length() == 32, "Invalid UUID string: %s", value); String high = value.substring(0, 16); String low = value.substring(16); return new UUID(Long.parseUnsignedLong(high, 16), diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Frequency.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/UnsafeUtil.java similarity index 52% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Frequency.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/util/UnsafeUtil.java index 3fd1c82332..bc6e492faa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Frequency.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/UnsafeUtil.java @@ -15,35 +15,33 @@ * limitations under the License. */ -package org.apache.hugegraph.type.define; +package org.apache.hugegraph.util; -public enum Frequency implements SerialEnum { +import java.lang.reflect.Field; - DEFAULT(0, "default"), +import sun.misc.Unsafe; - SINGLE(1, "single"), - - MULTIPLE(2, "multiple"); - - private byte code = 0; - private String name = null; +/** + * Shared access to the Unsafe instance used by native memory and concurrent collections. + */ +public final class UnsafeUtil { - static { - SerialEnum.register(Frequency.class); - } + private static final Unsafe UNSAFE = loadUnsafe(); - Frequency(int code, String name) { - assert code < 256; - this.code = (byte) code; - this.name = name; + private UnsafeUtil() { } - @Override - public byte code() { - return this.code; + public static Unsafe getUnsafe() { + return UNSAFE; } - public String string() { - return this.name; + private static Unsafe loadUnsafe() { + try { + Field field = Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + return (Unsafe) field.get(null); + } catch (ReflectiveOperationException | RuntimeException cause) { + throw new UnsupportedOperationException("Unsafe is not supported on this platform", cause); + } } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java index fb42b8416e..d345e26565 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/CollectionFactory.java @@ -1,20 +1,18 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.util.collection; @@ -27,6 +25,8 @@ import java.util.Map; import java.util.Set; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.type.define.CollectionType; import org.apache.hugegraph.util.E; import org.eclipse.collections.api.map.primitive.IntObjectMap; import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; @@ -35,9 +35,6 @@ import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap; import org.eclipse.collections.impl.set.mutable.UnifiedSet; -import org.apache.hugegraph.id.Id; -import org.apache.hugegraph.type.define.CollectionType; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -76,7 +73,7 @@ public static List newList(CollectionType type) { return new ObjectArrayList<>(); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -91,7 +88,7 @@ public static List newList(CollectionType type, return new ObjectArrayList<>(initialCapacity); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -106,7 +103,7 @@ public static List newList(CollectionType type, return new ObjectArrayList<>(collection); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -132,7 +129,7 @@ public static Set newSet(CollectionType type) { return new ObjectOpenHashSet<>(); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -147,7 +144,7 @@ public static Set newSet(CollectionType type, return new ObjectOpenHashSet<>(initialCapacity); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -162,7 +159,7 @@ public static Set newSet(CollectionType type, return new ObjectOpenHashSet<>(collection); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -192,7 +189,7 @@ public static Map newMap(CollectionType type) { return new Object2ObjectOpenHashMap<>(); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -207,7 +204,7 @@ public static Map newMap(CollectionType type, return new Object2ObjectOpenHashMap<>(initialCapacity); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -222,7 +219,7 @@ public static Map newMap(CollectionType type, return new Object2ObjectOpenHashMap<>(map); default: throw new AssertionError( - "Unsupported collection type: " + type); + "Unsupported collection type: " + type); } } @@ -230,18 +227,19 @@ public static MutableIntObjectMap newIntObjectMap() { return new IntObjectHashMap<>(); } - public static MutableIntObjectMap newIntObjectMap(int initialCapacity) { + public static MutableIntObjectMap newIntObjectMap( + int initialCapacity) { return new IntObjectHashMap<>(initialCapacity); } public static MutableIntObjectMap newIntObjectMap( - IntObjectMap map) { + IntObjectMap map) { return new IntObjectHashMap<>(map); } @SuppressWarnings("unchecked") public static MutableIntObjectMap newIntObjectMap( - Object... objects) { + Object... objects) { IntObjectHashMap map = IntObjectHashMap.newMap(); E.checkArgument(objects.length % 2 == 0, "Must provide even arguments for " + @@ -261,4 +259,22 @@ public IdSet newIdSet() { public static IdSet newIdSet(CollectionType type) { return new IdSet(type); } + + public static IntSet newIntSet() { + /* + * Resume to the old version like this: + * return concurrent ? new IntHashSet().asSynchronized() : + * new IntHashSet(); + */ + return new IntSet.IntSetBySegments(Integer.MAX_VALUE); + } + + public static IntMap newIntMap() { + /* + * Resume to the old version like this: + * return concurrent ? new IntIntHashMap().asSynchronized() : + * new IntIntHashMap(); + */ + return new IntMap.IntMapBySegments(Integer.MAX_VALUE); + } } diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IdSet.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IdSet.java index d77ddfb047..7f977b252b 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IdSet.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IdSet.java @@ -1,36 +1,33 @@ /* - * Copyright 2017 HugeGraph Authors - * * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.apache.hugegraph.util.collection; +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Set; + import org.apache.hugegraph.id.Id; import org.apache.hugegraph.id.IdGenerator; -import org.apache.hugegraph.type.define.CollectionType; - import org.apache.hugegraph.iterator.ExtendableIterator; +import org.apache.hugegraph.type.define.CollectionType; import org.eclipse.collections.api.iterator.MutableLongIterator; import org.eclipse.collections.impl.set.mutable.primitive.LongHashSet; -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Set; - public class IdSet extends AbstractSet { private final LongHashSet numberIds; @@ -67,8 +64,8 @@ public boolean contains(Object object) { @Override public Iterator iterator() { return new ExtendableIterator<>( - this.nonNumberIds.iterator(), - new EcIdIterator(this.numberIds.longIterator())); + this.nonNumberIds.iterator(), + new EcLongIdIterator(this.numberIds.longIterator())); } @Override @@ -94,11 +91,11 @@ public void clear() { this.nonNumberIds.clear(); } - private static class EcIdIterator implements Iterator { + private static class EcLongIdIterator implements Iterator { private final MutableLongIterator iterator; - public EcIdIterator(MutableLongIterator iter) { + public EcLongIdIterator(MutableLongIterator iter) { this.iterator = iter; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntIterator.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntIterator.java similarity index 100% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntIterator.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntIterator.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMap.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntMap.java similarity index 100% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMap.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntMap.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntSet.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntSet.java similarity index 99% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntSet.java rename to hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntSet.java index c40b731d8c..48cfe75f85 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntSet.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/collection/IntSet.java @@ -22,11 +22,10 @@ import java.util.function.Function; import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.UnsafeUtil; import org.eclipse.collections.api.collection.primitive.MutableIntCollection; import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet; -import io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess; - public interface IntSet { boolean add(int key); @@ -549,7 +548,7 @@ public boolean concurrent() { } int CPUS = Runtime.getRuntime().availableProcessors(); - sun.misc.Unsafe UNSAFE = UnsafeAccess.UNSAFE; + sun.misc.Unsafe UNSAFE = UnsafeUtil.getUnsafe(); long MOD64 = 0x3fL; int DIV64 = 6; diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/SchemaDriverTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/SchemaDriverTest.java deleted file mode 100644 index e5398c2fb1..0000000000 --- a/hugegraph-struct/src/test/java/org/apache/hugegraph/SchemaDriverTest.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hugegraph; - -import java.lang.reflect.Field; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import org.apache.hugegraph.exception.HugeException; -import org.apache.hugegraph.exception.NotAllowException; -import org.apache.hugegraph.pd.client.KvClient; -import org.apache.hugegraph.pd.client.PDConfig; -import org.apache.hugegraph.pd.common.PDException; -import org.apache.hugegraph.pd.grpc.kv.WatchResponse; -import org.junit.Assert; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class SchemaDriverTest { - - private AtomicReference instance; - private SchemaDriver previousInstance; - - @Before - public void setUp() throws Exception { - this.instance = instanceReference(); - this.previousInstance = this.instance.getAndSet(null); - } - - @After - public void tearDown() { - this.instance.set(this.previousInstance); - } - - @Test - public void testDestroyClosesOwnedKvClient() { - TrackingKvClient client = new TrackingKvClient(); - SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); - this.instance.set(driver); - - try { - SchemaDriver.destroy(); - - Assert.assertTrue(client.closed); - Assert.assertNull(SchemaDriver.getInstance()); - } finally { - client.close(); - } - } - - @Test - public void testDestroyUnpublishesInstanceBeforeClosingResources() throws Exception { - BlockingCloseKvClient client = new BlockingCloseKvClient(); - SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); - this.instance.set(driver); - Thread destroyThread = new Thread(SchemaDriver::destroy, "schema-driver-destroy"); - try { - destroyThread.start(); - client.awaitCloseStarted(); - - Assert.assertNull(SchemaDriver.getInstance()); - } finally { - client.allowClose.countDown(); - destroyThread.join(5000L); - client.close(); - } - - Assert.assertFalse(destroyThread.isAlive()); - Assert.assertTrue(client.closed); - } - - @Test - public void testInitDoesNotWaitForDestroyCleanup() throws Exception { - BlockingCloseKvClient client = new BlockingCloseKvClient(); - SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); - this.instance.set(driver); - AtomicReference initFailure = new AtomicReference<>(); - CountDownLatch initFinished = new CountDownLatch(1); - Thread destroyThread = new Thread(SchemaDriver::destroy, "schema-driver-destroy"); - Thread initThread = new Thread(() -> { - try { - SchemaDriver.init(PDConfig.of("127.0.0.1:8686"), 10, 60_000L); - } catch (Throwable throwable) { - initFailure.set(throwable); - } finally { - initFinished.countDown(); - } - }, "schema-driver-init"); - boolean initCompletedDuringCleanup; - try { - destroyThread.start(); - client.awaitCloseStarted(); - initThread.start(); - initCompletedDuringCleanup = initFinished.await(1L, TimeUnit.SECONDS); - } finally { - client.allowClose.countDown(); - destroyThread.join(5000L); - initThread.join(5000L); - client.close(); - } - - Assert.assertTrue(initCompletedDuringCleanup); - Assert.assertTrue(initFailure.get() instanceof NotAllowException); - Assert.assertFalse(destroyThread.isAlive()); - Assert.assertFalse(initThread.isAlive()); - } - - @Test - public void testConcurrentDestroyWaitsForCleanup() throws Exception { - BlockingCloseKvClient client = new BlockingCloseKvClient(); - SchemaDriver driver = new SchemaDriver(client, 10, 60_000L); - this.instance.set(driver); - CountDownLatch secondDestroyStarted = new CountDownLatch(1); - CountDownLatch secondDestroyReturned = new CountDownLatch(1); - Thread firstDestroy = new Thread(SchemaDriver::destroy, "schema-driver-destroy-first"); - Thread secondDestroy = new Thread(() -> { - secondDestroyStarted.countDown(); - SchemaDriver.destroy(); - secondDestroyReturned.countDown(); - }, "schema-driver-destroy-second"); - boolean returnedBeforeCleanup; - try { - firstDestroy.start(); - client.awaitCloseStarted(); - secondDestroy.start(); - Assert.assertTrue(secondDestroyStarted.await(5L, TimeUnit.SECONDS)); - returnedBeforeCleanup = secondDestroyReturned.await(500L, TimeUnit.MILLISECONDS); - } finally { - client.allowClose.countDown(); - firstDestroy.join(5000L); - secondDestroy.join(5000L); - client.close(); - } - - Assert.assertFalse(returnedBeforeCleanup); - Assert.assertFalse(firstDestroy.isAlive()); - Assert.assertFalse(secondDestroy.isAlive()); - } - - @Test - public void testConstructorFailureClosesOwnedKvClient() { - FailingListenKvClient client = new FailingListenKvClient(); - - try { - new SchemaDriver(client, 10, 60_000L); - Assert.fail("SchemaDriver construction should fail"); - } catch (HugeException expected) { - Assert.assertEquals(2, client.listenCalls); - Assert.assertTrue(client.closed); - } finally { - client.close(); - } - } - - @SuppressWarnings("unchecked") - private static AtomicReference instanceReference() throws Exception { - Field field = SchemaDriver.class.getDeclaredField("INSTANCE"); - field.setAccessible(true); - return (AtomicReference) field.get(null); - } - - private static class TrackingKvClient extends KvClient { - - protected volatile boolean closed; - - TrackingKvClient() { - super(PDConfig.of("127.0.0.1:8686")); - } - - @Override - public void listen(String key, Consumer consumer) throws PDException { - // Avoid opening a real PD stream while constructing SchemaDriver. - } - - @Override - public void close() { - this.closed = true; - super.close(); - } - } - - private static class BlockingCloseKvClient extends TrackingKvClient { - - private final CountDownLatch closeStarted = new CountDownLatch(1); - private final CountDownLatch allowClose = new CountDownLatch(1); - - @Override - public void close() { - this.closeStarted.countDown(); - try { - this.allowClose.await(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IllegalStateException("Client close was interrupted", e); - } - super.close(); - } - - private void awaitCloseStarted() throws InterruptedException { - Assert.assertTrue(this.closeStarted.await(5L, TimeUnit.SECONDS)); - } - } - - private static class FailingListenKvClient extends TrackingKvClient { - - private int listenCalls; - - @Override - public void listen(String key, Consumer consumer) throws PDException { - if (++this.listenCalls == 2) { - throw new PDException(-1, "listener startup failed"); - } - } - } -} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/backend/BackendColumnTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/backend/BackendColumnTest.java new file mode 100644 index 0000000000..a9f1a8b379 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/backend/BackendColumnTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.backend; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +public class BackendColumnTest { + + @Test + public void testColumnsWithEqualBytesHaveEqualHashes() { + BackendColumn first = BackendColumn.of(new byte[]{1, 2}, new byte[]{3, 4}); + BackendColumn same = BackendColumn.of(new byte[]{1, 2}, new byte[]{3, 4}); + Assert.assertEquals(first, same); + Assert.assertEquals(first.hashCode(), same.hashCode()); + Set columns = new HashSet<>(); + columns.add(first); + Assert.assertTrue(columns.contains(same)); + Assert.assertFalse(columns.add(same)); + Assert.assertNotEquals(first, BackendColumn.of(new byte[]{1, 2}, new byte[]{5})); + } + + @Test + public void testSharedColumnRetainsMutableByteArraysAndNameOrdering() { + byte[] name = new byte[]{1}; + byte[] value = new byte[]{2}; + BackendColumn column = BackendColumn.of(name, value); + Assert.assertSame(name, column.name); + Assert.assertSame(value, column.value); + Assert.assertTrue(column.compareTo(BackendColumn.of(new byte[]{2}, value)) < 0); + Assert.assertEquals(0, column.compareTo(BackendColumn.of(new byte[]{1}, new byte[]{3}))); + Assert.assertTrue(column.compareTo(null) > 0); + name[0] = 3; + Assert.assertEquals(3, column.name[0]); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreCodecTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreCodecTest.java new file mode 100644 index 0000000000..0e1f4ad525 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreCodecTest.java @@ -0,0 +1,487 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.compatibility; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.BufferUnderflowException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Properties; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.UUID; + +import org.apache.hugegraph.backend.BinaryId; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.serializer.BytesBuffer.IndexColumnName; +import org.apache.hugegraph.serializer.BytesBuffer.IndexExpiryLayout; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.util.Blob; +import org.apache.hugegraph.util.Bytes; +import org.junit.Assert; +import org.junit.Test; + +import com.google.gson.JsonParser; + +/** + * Golden fixtures were written by the pre-consolidation core, not this module. + * See compatibility/2f827d6e8/README.md for provenance and coverage limits. + */ +public class LegacyCoreCodecTest { + + private static final String FIXTURES = "/compatibility/2f827d6e8/"; + + @Test + public void testLegacyLongIdsAndVarLongs() throws IOException { + long[] values = {Long.MIN_VALUE, -16385L, -16384L, -129L, -128L, -1L, + 0L, 1L, 127L, 128L, 16383L, 16384L, Long.MAX_VALUE}; + for (long value : values) { + byte[] idBytes = fixture("id.long." + value); + BytesBuffer reader = BytesBuffer.wrap(idBytes); + Id actual = reader.readId(); + Assert.assertEquals(IdGenerator.of(value), actual); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(idBytes, + BytesBuffer.allocate(64).writeId(actual).bytes()); + + byte[] varLongBytes = fixture("vlong." + value); + reader = BytesBuffer.wrap(varLongBytes); + Assert.assertEquals(value, reader.readVLong()); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(varLongBytes, + BytesBuffer.allocate(64).writeVLong(value).bytes()); + } + } + + @Test + public void testLegacyVarInts() throws IOException { + int[] values = {Integer.MIN_VALUE, -129, -1, 0, 127, 128, 16383, 16384, + Integer.MAX_VALUE}; + for (int value : values) { + byte[] expected = fixture("vint." + value); + BytesBuffer reader = BytesBuffer.wrap(expected); + Assert.assertEquals(value, reader.readVInt()); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(expected, + BytesBuffer.allocate(64).writeVInt(value).bytes()); + } + } + + @Test + public void testLegacyTextAndUuidIds() throws IOException { + assertId("id.text", IdGenerator.of("alice")); + assertId("id.unicode", IdGenerator.of("顶点😀")); + assertId("id.uuid", IdGenerator.of( + UUID.fromString("01234567-89ab-cdef-0123-456789abcdef"))); + } + + @Test + public void testLegacyTextIdWidthBoundaries() throws IOException { + for (int length : new int[]{1, 64, 65, 256, 257, 16384}) { + String key = "id.text.length." + length; + Id expected = IdGenerator.of("x".repeat(length)); + assertId(key, expected); + // The historical struct boolean overload used the same layout. + byte[] legacy = fixture(key); + BytesBuffer reader = BytesBuffer.wrap(legacy); + Assert.assertEquals(expected, reader.readId(true)); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(legacy, + BytesBuffer.allocate(64).writeId(expected, true).bytes()); + } + Assert.assertThrows(IllegalArgumentException.class, + () -> BytesBuffer.allocate(64).writeId(IdGenerator.of(""))); + Assert.assertThrows(IllegalArgumentException.class, + () -> BytesBuffer.allocate(64).writeId(IdGenerator.of("x".repeat(16385)))); + } + + @Test + public void testLegacyEdgeIds() throws IOException { + assertEdge("edge.out", new EdgeId(IdGenerator.of("alice"), Directions.OUT, + IdGenerator.of(3L), IdGenerator.of(4L), "2026!x", IdGenerator.of(99L))); + assertEdge("edge.in", new EdgeId(IdGenerator.of(99L), Directions.IN, + IdGenerator.of(3L), IdGenerator.of(4L), "2026!x", IdGenerator.of("alice"))); + } + + @Test + public void testLegacyEdgeKeyPrefixAndSortSkipping() throws IOException { + byte[] legacy = fixture("edge.out"); + Id owner = IdGenerator.of("alice"); + byte[] withoutOwner = Arrays.copyOfRange(legacy, fixture("id.text").length, legacy.length); + BytesBuffer prefixless = BytesBuffer.wrap(withoutOwner); + EdgeId edge = prefixless.readEdgeId(false, owner); + Assert.assertEquals(owner, edge.ownerVertexId()); + Assert.assertEquals(Directions.OUT, edge.direction()); + Assert.assertEquals(IdGenerator.of(3L), edge.edgeLabelId()); + Assert.assertEquals(IdGenerator.of(4L), edge.subLabelId()); + Assert.assertEquals("2026!x", edge.sortValues()); + Assert.assertEquals(IdGenerator.of(99L), edge.otherVertexId()); + Assert.assertEquals(0, prefixless.remaining()); + BytesBuffer skipped = BytesBuffer.wrap(legacy); + EdgeId withoutSort = (EdgeId) skipped.readEdgeIdSkipSortValues(); + Assert.assertEquals(owner, withoutSort.ownerVertexId()); + Assert.assertEquals("", withoutSort.sortValues()); + Assert.assertEquals(IdGenerator.of(99L), withoutSort.otherVertexId()); + Assert.assertEquals(0, skipped.remaining()); + } + + @Test + public void testLegacyIndexKeyLayoutBoundaries() throws IOException { + Properties rows = new Properties(); + try (InputStream input = this.getClass().getResourceAsStream(FIXTURES + "core-rows.properties")) { + Assert.assertNotNull(input); + rows.load(input); + } + byte[] timed = Bytes.fromHex(rows.getProperty("index.secondary.column.0.name")); + byte[] indexPrefix = Bytes.fromHex(rows.getProperty("index.secondary.id")); + byte[] prefixless = Arrays.copyOfRange(timed, indexPrefix.length, timed.length); + BytesBuffer withPrefix = BytesBuffer.wrap(timed); + IndexColumnName parsed = withPrefix.readIndexColumnName(HugeType.SECONDARY_INDEX, true, + IndexExpiryLayout.REQUIRED); + Assert.assertArrayEquals(Arrays.copyOf(indexPrefix, indexPrefix.length - 1), parsed.indexId().asBytes()); + Assert.assertEquals(IdGenerator.of(1L), parsed.elementId()); + Assert.assertEquals(1609459260000L, parsed.expiredTime()); + Assert.assertTrue(parsed.hasExpiredTime()); + Assert.assertEquals(0, withPrefix.remaining()); + BytesBuffer noPrefix = BytesBuffer.wrap(prefixless); + parsed = noPrefix.readIndexColumnName(HugeType.SECONDARY_INDEX, false, IndexExpiryLayout.REQUIRED); + Assert.assertNull(parsed.indexId()); + Assert.assertEquals(IdGenerator.of(1L), parsed.elementId()); + Assert.assertEquals(1609459260000L, parsed.expiredTime()); + Assert.assertEquals(0, noPrefix.remaining()); + byte[] bare = Bytes.fromHex(rows.getProperty("index.system.column.0.name")); + parsed = BytesBuffer.wrap(bare).readIndexColumnName(HugeType.VERTEX_LABEL_INDEX, true, + IndexExpiryLayout.OPTIONAL); + Assert.assertEquals(0L, parsed.expiredTime()); + Assert.assertFalse(parsed.hasExpiredTime()); + byte[] withZero = Arrays.copyOf(bare, bare.length + 1); + withZero[bare.length] = fixture("vlong.0")[0]; + parsed = BytesBuffer.wrap(withZero).readIndexColumnName(HugeType.VERTEX_LABEL_INDEX, true, + IndexExpiryLayout.OPTIONAL); + Assert.assertEquals(0L, parsed.expiredTime()); + Assert.assertTrue(parsed.hasExpiredTime()); + Assert.assertThrows(BufferUnderflowException.class, + () -> BytesBuffer.wrap(bare).readIndexColumnName( + HugeType.VERTEX_LABEL_INDEX, true, IndexExpiryLayout.REQUIRED)); + } + + @Test + public void testLegacyScalarProperties() throws IOException { + assertProperty(DataType.BOOLEAN, true); + assertProperty(DataType.BYTE, (byte) -7); + assertProperty(DataType.INT, -123456); + assertProperty(DataType.LONG, Long.MIN_VALUE); + assertProperty(DataType.FLOAT, 1.25f); + assertProperty(DataType.DOUBLE, -123.125d); + assertProperty(DataType.DATE, new Date(1609459200123L)); + assertProperty(DataType.TEXT, "属性😀\u0000"); + assertProperty(DataType.BLOB, Blob.wrap(new byte[]{0, -1, 1, 127, -128})); + assertProperty(DataType.UUID, UUID.fromString("01234567-89ab-cdef-0123-456789abcdef")); + } + + @Test + public void testLegacyKryoProperties() throws IOException { + assertProperty(DataType.OBJECT, new ArrayList<>(Arrays.asList("legacy", 7, true))); + assertProperty(DataType.UNKNOWN, "legacy-object"); + } + + @Test + public void testLegacySchemaDrivenProperties() throws IOException { + assertSchemaProperty("single", Cardinality.SINGLE, 7); + assertSchemaProperty("list", Cardinality.LIST, Arrays.asList(7, -1, 7)); + assertSchemaProperty("set", Cardinality.SET, + new LinkedHashSet<>(Arrays.asList(7, -1))); + } + + @Test + public void testLegacyIndexIds() throws IOException { + assertIndex("index.string", HugeType.SECONDARY_INDEX, + "label!alice".getBytes(StandardCharsets.UTF_8)); + assertIndex("index.int", HugeType.RANGE_INT_INDEX, + new byte[]{(byte) 160, 0, 0, 0, 3, (byte) 128, 0, 0, 7}); + assertIndex("index.long", HugeType.RANGE_LONG_INDEX, + new byte[]{(byte) 162, 0, 0, 0, 3, (byte) 128, 0, 0, 0, 0, 0, 0, 7}); + } + + @Test + public void testLegacyTaggedScalarProperties() throws IOException { + assertTaggedScalar(DataType.BOOLEAN, true); + assertTaggedScalar(DataType.BYTE, (byte) -7); + assertTaggedScalar(DataType.INT, -123456); + assertTaggedScalar(DataType.LONG, Long.MIN_VALUE); + assertTaggedScalar(DataType.FLOAT, 1.25f); + assertTaggedScalar(DataType.DOUBLE, -123.125d); + assertTaggedScalar(DataType.DATE, new Date(1609459200123L)); + assertTaggedScalar(DataType.TEXT, "属性😀\u0000"); + assertTaggedScalar(DataType.BLOB, Blob.wrap(new byte[]{0, -1, 1, 127, -128})); + assertTaggedScalar(DataType.UUID, + UUID.fromString("01234567-89ab-cdef-0123-456789abcdef")); + } + + @Test + public void testLegacyTaggedCollectionProperties() throws IOException { + assertTaggedProperty("list", DataType.INT, Cardinality.LIST, + Arrays.asList(7, -1, 7), "schema.list"); + assertTaggedProperty("set", DataType.INT, Cardinality.SET, + new LinkedHashSet<>(Arrays.asList(7, -1)), "schema.set"); + } + + @Test + public void testSkippingLegacyPropertiesPreservesTrailingTtl() throws IOException { + for (DataType type : DataType.values()) { + this.assertSkipProperty("property." + type.name(), type, Cardinality.SINGLE); + byte[] legacy = type == DataType.UNKNOWN || type == DataType.OBJECT ? null : + fixture("struct-tagged-properties.hex", type.name()); + if (legacy != null) { + BytesBuffer buffer = withTrailingMarker(legacy); + buffer.skipProperty(); + assertTrailingMarker(buffer); + } + } + this.assertSkipProperty("schema.list", DataType.INT, Cardinality.LIST); + this.assertSkipProperty("schema.set", DataType.INT, Cardinality.SET); + // An existing core Kryo limitation must not prevent skipping data: + // this collection's baseline writer can encode it, but its reader + // cannot instantiate Arrays$ArrayList. + this.assertSkipProperty("property.OBJECT_UNSUPPORTED_COLLECTION", + DataType.OBJECT, Cardinality.SINGLE); + } + + private void assertSkipProperty(String name, DataType type, Cardinality cardinality) + throws IOException { + PropertyKey key = new PropertyKey(null, IdGenerator.of(101L), "legacy"); + key.dataType(type); + key.cardinality(cardinality); + BytesBuffer buffer = withTrailingMarker(fixture(name)); + buffer.skipSchemaProperty(key); + assertTrailingMarker(buffer); + } + + private static BytesBuffer withTrailingMarker(byte[] bytes) { + BytesBuffer buffer = BytesBuffer.allocate(bytes.length + 16); + buffer.write(bytes); + buffer.writeUInt8(0x55); + buffer.writeVLong(1609459260000L); + return buffer.forReadWritten(); + } + + private static void assertTrailingMarker(BytesBuffer buffer) { + Assert.assertEquals(0x55, buffer.readUInt8()); + Assert.assertEquals(1609459260000L, buffer.readVLong()); + Assert.assertEquals(0, buffer.remaining()); + } + + @Test + public void testLegacyVertexQuery() throws IOException, ParseException { + // Legacy JSON date strings represent wall time in the process time + // zone. Do not mutate it after Gson's date adapter initialization. + ConditionQuery query = ConditionQuery.fromBytes(jsonFixture("core-query.json.txt")); + Assert.assertEquals(HugeType.VERTEX, query.resultType()); + Assert.assertEquals(7L, query.offset()); + Assert.assertEquals(19L, query.limit()); + Assert.assertEquals(IdGenerator.of(3L), query.condition(HugeKeys.LABEL)); + Condition.Relation range = query.relation(IdGenerator.of(11L)); + Assert.assertEquals(Condition.RelationType.GTE, range.relation()); + Assert.assertEquals(18, range.value()); + Assert.assertNull(query.condition(IdGenerator.of(11L))); + Assert.assertEquals(Arrays.asList(20L, 30L), query.condition(IdGenerator.of(12L))); + Date expectedDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT) + .parse("2021-01-01 00:00:00.123"); + Assert.assertEquals(expectedDate, query.condition(IdGenerator.of(13L))); + Assert.assertEquals(5, query.conditions().size()); + Condition disjunction = query.conditions().stream() + .filter(c -> c instanceof Condition.Or) + .findFirst().orElseThrow(AssertionError::new); + Assert.assertTrue(disjunction.test("alice")); + Assert.assertTrue(disjunction.test("bob")); + Assert.assertFalse(disjunction.test("charlie")); + } + + @Test + public void testLegacyEdgeQuery() throws IOException { + ConditionQuery query = ConditionQuery.fromBytes(jsonFixture("core-edge-query.json.txt")); + Assert.assertEquals(HugeType.EDGE, query.resultType()); + Assert.assertEquals(IdGenerator.of("alice"), query.condition(HugeKeys.OWNER_VERTEX)); + Assert.assertEquals(Directions.OUT, query.condition(HugeKeys.DIRECTION)); + Assert.assertEquals(IdGenerator.of(3L), query.condition(HugeKeys.LABEL)); + Assert.assertEquals("AQIDBA==", query.page()); + Assert.assertEquals(5L, query.limit()); + Assert.assertEquals(3, query.conditions().size()); + } + + @Test + public void testLegacyCountAggregateQuery() throws IOException { + byte[] payload = jsonFixture("core-count-query.json.txt"); + ConditionQuery query = ConditionQuery.fromBytes(payload); + Assert.assertEquals(AggregateFunc.COUNT, query.aggregateNotNull().func()); + Assert.assertTrue(query.aggregateNotNull().countAll()); + Assert.assertNull(query.aggregateNotNull().column()); + Assert.assertEquals(5L, query.aggregateNotNull() + .reduce(Arrays.asList(2L, 3L).iterator()).longValue()); + assertAggregateJson(payload, query.bytes()); + } + + @Test + public void testLegacyAvgAggregateQuery() throws IOException { + byte[] payload = jsonFixture("core-avg-query.json.txt"); + ConditionQuery query = ConditionQuery.fromBytes(payload); + Assert.assertEquals(AggregateFunc.AVG, query.aggregateNotNull().func()); + Assert.assertFalse(query.aggregateNotNull().countAll()); + Assert.assertEquals("age", query.aggregateNotNull().column()); + Assert.assertEquals(25d, query.aggregateNotNull() + .reduce(Arrays.asList(20, 30).iterator()).doubleValue(), + 0d); + Assert.assertEquals(IdGenerator.of(3L), query.condition(HugeKeys.LABEL)); + assertAggregateJson(payload, query.bytes()); + } + + private static void assertAggregateJson(byte[] legacy, byte[] current) { + Assert.assertEquals(JsonParser.parseString(new String(legacy, StandardCharsets.UTF_8)) + .getAsJsonObject().get("aggregate"), + JsonParser.parseString(new String(current, StandardCharsets.UTF_8)) + .getAsJsonObject().get("aggregate")); + } + + private static void assertId(String key, Id expected) throws IOException { + byte[] legacy = fixture(key); + BytesBuffer reader = BytesBuffer.wrap(legacy); + Assert.assertEquals(expected, reader.readId()); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(legacy, BytesBuffer.allocate(64).writeId(expected).bytes()); + } + + private static void assertEdge(String key, EdgeId expected) throws IOException { + byte[] legacy = fixture(key); + BytesBuffer reader = BytesBuffer.wrap(legacy); + EdgeId actual = (EdgeId) reader.readEdgeId(); + Assert.assertEquals(expected.ownerVertexId(), actual.ownerVertexId()); + Assert.assertEquals(expected.direction(), actual.direction()); + Assert.assertEquals(expected.edgeLabelId(), actual.edgeLabelId()); + Assert.assertEquals(expected.subLabelId(), actual.subLabelId()); + Assert.assertEquals(expected.sortValues(), actual.sortValues()); + Assert.assertEquals(expected.otherVertexId(), actual.otherVertexId()); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(legacy, BytesBuffer.allocate(128).writeEdgeId(expected).bytes()); + } + + private static void assertProperty(DataType type, Object expected) throws IOException { + byte[] legacy = fixture("property." + type.name()); + BytesBuffer reader = BytesBuffer.wrap(legacy); + Assert.assertEquals(expected, reader.readProperty(type)); + Assert.assertEquals(0, reader.remaining()); + BytesBuffer writer = BytesBuffer.allocate(128); + writer.writeProperty(type, expected); + Assert.assertArrayEquals(legacy, writer.bytes()); + } + + private static void assertSchemaProperty(String name, Cardinality cardinality, + Object expected) throws IOException { + PropertyKey key = new PropertyKey(null, IdGenerator.of(101L), "legacy"); + key.dataType(DataType.INT); + key.cardinality(cardinality); + byte[] legacy = fixture("schema." + name); + BytesBuffer reader = BytesBuffer.wrap(legacy); + Assert.assertEquals(expected, reader.readSchemaProperty(key)); + Assert.assertEquals(0, reader.remaining()); + Assert.assertEquals(cardinality, key.cardinality()); + Assert.assertEquals(DataType.INT, key.dataType()); + Assert.assertArrayEquals(legacy, + BytesBuffer.allocate(64).writeSchemaProperty(key, expected).bytes()); + } + + private static void assertIndex(String name, HugeType type, byte[] expected) + throws IOException { + byte[] legacy = fixture(name); + BytesBuffer reader = BytesBuffer.wrap(legacy); + Assert.assertArrayEquals(expected, reader.readIndexId(type).asBytes()); + Assert.assertEquals(0, reader.remaining()); + Assert.assertArrayEquals(legacy, BytesBuffer.allocate(64) + .writeIndexId(new BinaryId(expected, null), type) + .bytes()); + } + + private static void assertTaggedScalar(DataType type, Object expected) throws IOException { + assertTaggedProperty(type.name(), type, Cardinality.SINGLE, + expected, "property." + type.name()); + } + + private static void assertTaggedProperty(String name, DataType type, + Cardinality cardinality, Object expected, + String rawKey) throws IOException { + byte[] legacy = fixture("struct-tagged-properties.hex", name); + byte[] raw = fixture(rawKey); + Assert.assertEquals(raw.length + 1, legacy.length); + Assert.assertArrayEquals(raw, Arrays.copyOfRange(legacy, 1, legacy.length)); + PropertyKey key = new PropertyKey(null, IdGenerator.of(101L), "legacy"); + // Tagged readers must recover metadata, even when the caller starts + // with metadata different from the encoded property. + key.dataType(DataType.UNKNOWN); + key.cardinality(Cardinality.SET); + BytesBuffer reader = BytesBuffer.wrap(legacy); + Assert.assertEquals(expected, reader.readProperty(key)); + Assert.assertEquals(0, reader.remaining()); + Assert.assertEquals(type, key.dataType()); + Assert.assertEquals(cardinality, key.cardinality()); + Assert.assertArrayEquals(legacy, + BytesBuffer.allocate(128).writeProperty(key, expected).bytes()); + } + + private static byte[] fixture(String key) throws IOException { + return fixture("core-codecs.hex", key); + } + + private static byte[] fixture(String file, String key) throws IOException { + Properties properties = new Properties(); + try (InputStream input = LegacyCoreCodecTest.class.getResourceAsStream( + FIXTURES + file)) { + Assert.assertNotNull("Missing codec fixture resource", input); + properties.load(input); + } + String hex = properties.getProperty(key); + Assert.assertNotNull("Missing legacy fixture " + key, hex); + return Bytes.fromHex(hex); + } + + private static byte[] jsonFixture(String name) throws IOException { + try (InputStream input = LegacyCoreCodecTest.class.getResourceAsStream(FIXTURES + name)) { + Assert.assertNotNull("Missing legacy fixture " + name, input); + String text = new String(input.readAllBytes(), StandardCharsets.UTF_8); + Assert.assertTrue("Missing fixture license prolog", text.startsWith("/*")); + int payloadStart = text.indexOf("*/\n") + 3; + Assert.assertTrue("Missing fixture payload", payloadStart > 3); + Assert.assertTrue("Missing fixture file newline", text.endsWith("\n")); + return text.substring(payloadStart, text.length() - 1).getBytes(StandardCharsets.UTF_8); + } + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreRowCodecTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreRowCodecTest.java new file mode 100644 index 0000000000..0e48381070 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyCoreRowCodecTest.java @@ -0,0 +1,323 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.compatibility; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.serializer.DirectBinarySerializer; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.BaseEdge; +import org.apache.hugegraph.structure.BaseElement; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.type.define.WriteType; +import org.apache.hugegraph.util.Bytes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Test complete rows written by the pinned pre-consolidation BinarySerializer. */ +public class LegacyCoreRowCodecTest { + + private final BinaryElementSerializer serializer = new BinaryElementSerializer(); + private final DirectBinarySerializer direct = new DirectBinarySerializer(); + private final Map properties = new HashMap<>(); + private final Map vertices = new HashMap<>(); + private final Map edges = new HashMap<>(); + private final Map indexes = new HashMap<>(); + private Properties rows; + private HugeGraphSupplier graph; + private long expiry; + + @Before + public void prepare() throws IOException { + this.rows = new Properties(); + try (InputStream input = this.getClass().getResourceAsStream( + "/compatibility/2f827d6e8/core-rows.properties")) { + Assert.assertNotNull(input); + this.rows.load(input); + } + this.expiry = Long.parseLong(this.rows.getProperty("expiry")); + this.graph = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, args) -> { + switch (method.getName()) { + case "now": return Long.parseLong(this.rows.getProperty("now")); + case "name": + case "spaceGraphName": return "legacy-fixture"; + case "propertyKey": return this.properties.get(((Id) args[0]).asLong()); + case "vertexLabel": + case "vertexLabelOrNone": return this.vertices.get(((Id) args[0]).asLong()); + case "edgeLabel": + case "edgeLabelOrNone": return this.edges.get(((Id) args[0]).asLong()); + case "indexLabel": return this.indexes.get(((Id) args[0]).asLong()); + default: throw new AssertionError("Unexpected supplier call: " + method); + } + }); + this.property(1L, "age", DataType.INT, Cardinality.SINGLE); + this.property(2L, "scores", DataType.INT, Cardinality.LIST); + this.property(3L, "groups", DataType.INT, Cardinality.SET); + this.property(9L, "rank", DataType.INT, Cardinality.SINGLE) + .writeType(WriteType.OLAP_COMMON); + this.property(16L, "weight", DataType.LONG, Cardinality.SINGLE); + this.property(17L, "name", DataType.TEXT, Cardinality.SINGLE); + this.vertexLabel(4L, "person", 60000L); + this.vertexLabel(10L, "timeless", 0L); + this.edgeLabel(5L, "knows", 60000L); + this.edgeLabel(11L, "untimed", 0L); + this.indexLabel(6L, IndexType.SECONDARY, 4L); + this.indexLabel(7L, IndexType.RANGE_INT, 4L); + this.indexLabel(8L, IndexType.RANGE_LONG, 4L); + this.indexLabel(12L, IndexType.SECONDARY, 10L); + this.indexLabel(13L, IndexType.RANGE_INT, 10L); + this.indexLabel(14L, IndexType.RANGE_LONG, 10L); + this.indexLabel(15L, IndexType.SECONDARY, 4L); + } + + @Test + public void testLegacyVertexRowsAndDirectTtl() { + for (String name : new String[]{"vertex", "vertex.untimed"}) { + BackendColumn column = this.column(name); + BaseVertex vertex = this.serializer.parseSchemaVertex(this.graph, column, null); + this.assertProperties(vertex); + Assert.assertEquals(name.endsWith("untimed") ? 3L : 1L, vertex.id().asLong()); + long expectedExpiry = name.endsWith("untimed") ? 0L : this.expiry; + Assert.assertEquals(expectedExpiry, vertex.expiredTime()); + Assert.assertArrayEquals(column.value, this.serializer.formatSchemaVertexValue(vertex)); + Assert.assertEquals(expectedExpiry, this.direct.parseSchemaVertex( + this.graph, column.name, column.value).expiredTime()); + } + } + + @Test + public void testLegacyEdgeRowsAndDirectTtl() { + for (String name : new String[]{"edge.out", "edge.in", "edge.untimed"}) { + BackendColumn column = this.column(name); + BaseEdge edge = this.serializer.parseSchemaEdge(this.graph, column, null, true); + this.assertProperties(edge); + Assert.assertEquals(!name.equals("edge.in"), edge.isOutEdge()); + Assert.assertEquals(name.equals("edge.in") ? 2L : 1L, edge.ownerVertexId().asLong()); + long expectedExpiry = name.endsWith("untimed") ? 0L : this.expiry; + Assert.assertEquals(expectedExpiry, edge.expiredTime()); + Assert.assertArrayEquals(column.name, this.serializer.formatEdgeName(edge)); + Assert.assertArrayEquals(column.value, this.serializer.formatSchemaEdgeValue(edge)); + Assert.assertEquals(expectedExpiry, this.direct.parseSchemaEdge( + this.graph, column.name, column.value).expiredTime()); + } + } + + @Test + public void testLegacyVertexWithOlapMergedRow() { + BaseVertex vertex = this.serializer.parseSchemaVertexFromCols( + this.graph, this.column("vertex"), this.column("olap")); + Assert.assertEquals(1L, vertex.id().asLong()); + Assert.assertEquals(this.expiry, vertex.expiredTime()); + this.assertProperties(vertex); + Assert.assertEquals(42, (int) vertex.getPropertyValue(IdGenerator.of(9L))); + } + + @Test + public void testLegacyStandaloneOlapRow() { + BaseVertex vertex = this.serializer.parseSchemaVertexOlap( + this.graph, this.column("olap"), null); + Assert.assertEquals(1L, vertex.id().asLong()); + Assert.assertEquals(42, (int) vertex.getPropertyValue(IdGenerator.of(9L))); + Assert.assertEquals(0L, vertex.expiredTime()); + } + + @Test + public void testSharedIndexWriterRetainsLegacyCoreBytes() { + for (String name : new String[]{"index.secondary", "index.int", "index.long", + "index.secondary.untimed", "index.int.untimed", + "index.long.untimed", "index.hashed", "index.system", "index.system.edge"}) { + BackendColumn legacy = this.column(name); + Index decoded = this.serializer.parseSchemaIndex(this.graph, legacy); + BackendColumn current = this.serializer.writeSchemaIndex(decoded); + Assert.assertArrayEquals(name + " key", legacy.name, current.name); + Assert.assertNotNull(name + " persistent value", current.value); + Assert.assertArrayEquals(name + " value", legacy.value, current.value); + } + } + + @Test + public void testOriginalStoreIndexTtlRows() throws IOException { + Properties legacy = new Properties(); + try (InputStream input = this.getClass().getResourceAsStream( + "/compatibility/2f827d6e8/store-index-rows.properties")) { + Assert.assertNotNull(input); + legacy.load(input); + } + for (String name : new String[]{"secondary", "int", "long", "system", "system.edge"}) { + BackendColumn column = BackendColumn.of(Bytes.fromHex(legacy.getProperty(name + ".name")), + Bytes.fromHex(legacy.getProperty(name + ".value"))); + Index decoded = this.serializer.parseSchemaIndex(this.graph, column); + Id expectedElement = name.equals("system.edge") ? edgeElementId() : IdGenerator.of(1L); + Assert.assertEquals(expectedElement, decoded.elementId()); + Assert.assertEquals(this.expiry, decoded.expiredTime()); + Assert.assertEquals(this.expiry, this.direct.parseSchemaIndex( + this.graph, column.name, column.value).expiredTime()); + // The still-supported tagged writer must also retain old Store bytes. + BackendColumn tagged = this.serializer.writeIndex(decoded); + Assert.assertArrayEquals(column.name, tagged.name); + Assert.assertArrayEquals(column.value, tagged.value); + if (name.startsWith("system")) { + BackendColumn current = this.serializer.writeSchemaIndex(decoded); + Assert.assertArrayEquals(column.name, current.name); + Assert.assertArrayEquals(column.value, current.value); + Assert.assertFalse(decoded.hasTtl()); + } + } + } + + @Test + public void testPositiveLabelExpiryUsesStableStorageKeyAndCoreFlag() throws IOException { + Properties storage = new Properties(); + try (InputStream input = this.getClass().getResourceAsStream( + "/compatibility/2f827d6e8/store-index-rows.properties")) { + Assert.assertNotNull(input); + storage.load(input); + } + for (String name : new String[]{"system", "system.edge"}) { + HugeType base = name.endsWith("edge") ? HugeType.EDGE : HugeType.VERTEX; + Id elementId = name.endsWith("edge") ? edgeElementId() : IdGenerator.of(1L); + Index index = new Index(this.graph, IndexLabel.label(base), true); + index.fieldValues(name.endsWith("edge") ? 5L : 4L); + index.elementIds(elementId, this.expiry); + Assert.assertFalse(index.hasTtl()); + BackendColumn oldCore = this.column("index." + name); + BackendColumn core = this.serializer.formatSchemaIndex(index.type(), index.indexLabelId(), + index.fieldValues(), elementId, true, false, this.expiry); + Assert.assertArrayEquals(oldCore.name, core.name); + Assert.assertNotNull(core.value); + Assert.assertArrayEquals(oldCore.value, core.value); + BackendColumn stored = this.serializer.writeSchemaIndex(index); + Assert.assertArrayEquals(Bytes.fromHex(storage.getProperty(name + ".name")), stored.name); + Assert.assertArrayEquals(Bytes.fromHex(storage.getProperty(name + ".value")), stored.value); + Assert.assertArrayEquals("Storage append retains Core elimination key", core.name, stored.name); + Assert.assertEquals(this.expiry, this.direct.parseSchemaIndex( + this.graph, stored.name, stored.value).expiredTime()); + Assert.assertEquals(Long.valueOf(this.expiry), this.serializer.storedLabelIndexExpiredTime( + index.type(), true, stored.value)); + Assert.assertNull(this.serializer.storedLabelIndexExpiredTime(index.type(), false, stored.value)); + Assert.assertNull(this.serializer.storedLabelIndexExpiredTime( + HugeType.SECONDARY_INDEX, true, stored.value)); + Assert.assertNull(this.serializer.storedLabelIndexExpiredTime( + index.type(), true, Arrays.copyOf(stored.value, stored.value.length + 1))); + } + } + + private static Id edgeElementId() { + return new EdgeId(IdGenerator.of(1L), Directions.OUT, IdGenerator.of(5L), + IdGenerator.of(5L), "2026!x", IdGenerator.of(2L)); + } + + @Test + public void testLegacyIndexRowsAndDirectTtl() { + for (String name : new String[]{"index.secondary", "index.int", "index.long", + "index.secondary.untimed", "index.int.untimed", + "index.long.untimed", "index.hashed", "index.system", "index.system.edge"}) { + BackendColumn column = this.column(name); + Index index = this.serializer.parseSchemaIndex(this.graph, column); + Assert.assertEquals(name.equals("index.system.edge") ? edgeElementId() : IdGenerator.of(1L), + index.elementId()); + long expectedExpiry = name.endsWith("untimed") || name.startsWith("index.system") ? + 0L : this.expiry; + Assert.assertEquals(expectedExpiry, index.expiredTime()); + Assert.assertEquals(expectedExpiry, this.direct.parseSchemaIndex( + this.graph, column.name, column.value).expiredTime()); + if (name.equals("index.hashed")) { + Assert.assertEquals("long-field-".repeat(20), index.fieldValues()); + } else if (name.startsWith("index.secondary")) { + Assert.assertEquals("alice", index.fieldValues()); + } else if (name.startsWith("index.int")) { + Assert.assertEquals(7, index.fieldValues()); + } else if (name.startsWith("index.long")) { + Assert.assertEquals(7L, index.fieldValues()); + } + } + } + + private void assertProperties(BaseElement element) { + Assert.assertEquals(7, (int) element.getPropertyValue(IdGenerator.of(1L))); + Assert.assertEquals(Arrays.asList(7, -1, 7), element.getPropertyValue(IdGenerator.of(2L))); + Assert.assertEquals(new HashSet<>(Arrays.asList(7, -1)), + element.getPropertyValue(IdGenerator.of(3L))); + } + + private BackendColumn column(String name) { + return BackendColumn.of(Bytes.fromHex(this.rows.getProperty(name + ".column.0.name")), + Bytes.fromHex(this.rows.getProperty(name + ".column.0.value"))); + } + + private PropertyKey property(long id, String name, DataType type, Cardinality cardinality) { + PropertyKey key = new PropertyKey(this.graph, IdGenerator.of(id), name); + key.dataType(type); + key.cardinality(cardinality); + this.properties.put(id, key); + return key; + } + + private void vertexLabel(long id, String name, long ttl) { + VertexLabel label = new VertexLabel(this.graph, IdGenerator.of(id), name); + label.ttl(ttl); + label.properties(IdGenerator.of(1L), IdGenerator.of(2L), IdGenerator.of(3L)); + this.vertices.put(id, label); + } + + private void edgeLabel(long id, String name, long ttl) { + EdgeLabel label = new EdgeLabel(this.graph, IdGenerator.of(id), name); + label.ttl(ttl); + label.frequency(Frequency.MULTIPLE); + label.links(Pair.of(IdGenerator.of(4L), IdGenerator.of(4L))); + label.properties(IdGenerator.of(1L), IdGenerator.of(2L), IdGenerator.of(3L)); + this.edges.put(id, label); + } + + private void indexLabel(long id, IndexType type, long baseId) { + IndexLabel label = new IndexLabel(this.graph, IdGenerator.of(id), "index-" + id); + label.indexType(type); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(IdGenerator.of(baseId)); + label.indexFields(IdGenerator.of(type == IndexType.RANGE_LONG ? 16L : + type == IndexType.SECONDARY ? 17L : 1L)); + this.indexes.put(id, label); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java new file mode 100644 index 0000000000..a63fe4e78d --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.compatibility; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.backend.BinaryId; +import org.apache.hugegraph.backend.Shard; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.IdUtil; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.ConditionQuery; +import org.apache.hugegraph.query.Query; +import org.apache.hugegraph.query.serializer.AbstractSerializerAdapter; +import org.apache.hugegraph.query.serializer.QueryAdapter; +import org.apache.hugegraph.query.serializer.QueryIdAdapter; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.SchemaElement; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.struct.schema.builder.SchemaBuilder; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.type.GraphType; +import org.apache.hugegraph.type.Indexfiable; +import org.apache.hugegraph.type.Namifiable; +import org.apache.hugegraph.type.Propfiable; +import org.apache.hugegraph.type.Typifiable; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.util.Bytes; +import org.apache.hugegraph.util.KryoUtil; +import org.apache.hugegraph.util.LegacyClassNames; +import org.apache.tinkerpop.shaded.kryo.KryoException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Original core OBJECT payloads and original default-reader receipts. */ +public class LegacyKryoCompatibilityTest { + + private Properties fixtures; + + @Before + public void prepare() throws IOException { + this.fixtures = new Properties(); + try (InputStream input = this.getClass().getResourceAsStream( + "/compatibility/2f827d6e8/core-kryo-objects.properties")) { + Assert.assertNotNull(input); + this.fixtures.load(input); + } + } + + @Test + public void testReadableRelocatedEnumsAndClassLiteral() { + this.assertValue("aggregate_func", AggregateFunc.AVG); + this.assertValue("relation_type", Condition.RelationType.GTE); + this.assertValue("condition_type", Condition.ConditionType.OR); + this.assertValue("query_order", Query.Order.DESC); + this.assertValue("query_order_type", Query.OrderType.ORDER_STRICT); + this.assertValue("optimized_type", ConditionQuery.OptimizedType.INDEX_FILTER); + this.assertValue("id_type", Id.IdType.UUID); + this.assertValue("graph_type_class", GraphType.class); + } + + @Test + public void testReadableRelocatedUserdata() { + Object decoded = this.read("userdata"); + Assert.assertEquals(Userdata.class, decoded.getClass()); + Assert.assertEquals(expectedUserdata(), decoded); + Assert.assertEquals(decoded, roundTrip(decoded)); + } + + @Test + public void testReadableRelocatedArrayTypes() { + Object ids = this.read("id_array"); + Assert.assertEquals(Id[].class, ids.getClass()); + Assert.assertArrayEquals(new Id[]{null}, (Id[]) ids); + Assert.assertArrayEquals((Id[]) ids, (Id[]) roundTrip(ids)); + Object matrix = this.read("id_matrix"); + Assert.assertEquals(Id[][].class, matrix.getClass()); + Assert.assertArrayEquals(new Id[][]{new Id[]{null}, new Id[0]}, (Id[][]) matrix); + Assert.assertArrayEquals((Id[][]) matrix, (Id[][]) roundTrip(matrix)); + Object shards = this.read("shard_array"); + Assert.assertEquals(Shard[].class, shards.getClass()); + Assert.assertArrayEquals(new Shard[]{null}, (Shard[]) shards); + Assert.assertArrayEquals((Shard[]) shards, (Shard[]) roundTrip(shards)); + Object schemas = this.read("schema_array"); + Assert.assertEquals(PropertyKey[].class, schemas.getClass()); + Assert.assertArrayEquals(new PropertyKey[]{null}, (PropertyKey[]) schemas); + Assert.assertArrayEquals((PropertyKey[]) schemas, (PropertyKey[]) roundTrip(schemas)); + } + + @Test + public void testReadableNestedClassAndArrayGraphs() { + Object classes = this.read("class_list"); + Assert.assertEquals(expectedClasses(), classes); + Assert.assertEquals(classes, roundTrip(classes)); + Object nested = this.read("nested"); + assertNested(nested); + assertNested(roundTrip(nested)); + } + + @Test + public void testReadableRenamedContractAndUtilityClassLiterals() { + List> expected = Arrays.asList(Namifiable.class, Typifiable.class, + Indexfiable.class, Propfiable.class, IdUtil.class, + SplicingIdGenerator.class, SchemaBuilder.class, + AbstractSerializerAdapter.class, QueryAdapter.class, + QueryIdAdapter.class); + Object decoded = this.read("contract_classes"); + Assert.assertEquals(expected, decoded); + Assert.assertEquals(expected, roundTrip(decoded)); + } + + @Test + public void testReadableLegacyBackendColumn() { + this.assertValue("backend_column_class", BackendColumn.class); + Object decoded = this.read("backend_column"); + assertColumn(decoded); + assertColumn(roundTrip(decoded)); + Object array = this.read("backend_column_array"); + Assert.assertEquals(BackendColumn[].class, array.getClass()); + Assert.assertEquals(2, ((BackendColumn[]) array).length); + assertColumn(((BackendColumn[]) array)[0]); + Assert.assertNull(((BackendColumn[]) array)[1]); + assertColumn(((BackendColumn[]) roundTrip(array))[0]); + } + + @Test + public void testReadableNestedSchemaClassLiteralsAndArrays() { + List> expected = Arrays.asList(SchemaElement.TaskWithSchema.class, + nestedClass(PropertyKey.class, "P"), nestedClass(VertexLabel.class, "P"), + nestedClass(EdgeLabel.class, "P"), nestedClass(IndexLabel.class, "P"), + SchemaElement.P.class, PropertyKey.Builder.class, VertexLabel.Builder.class, + EdgeLabel.Builder.class, IndexLabel.Builder.class); + Object classes = this.read("schema_nested_classes"); + Assert.assertEquals(expected, classes); + Assert.assertEquals(expected, roundTrip(classes)); + List arrays = (List) this.read("schema_nested_arrays"); + List written = (List) roundTrip(arrays); + for (int i = 0; i < expected.size(); i++) { + Class arrayClass = Array.newInstance(expected.get(i), 1).getClass(); + Assert.assertEquals(arrayClass, arrays.get(i).getClass()); + Assert.assertEquals(arrayClass, written.get(i).getClass()); + Assert.assertEquals(1, Array.getLength(arrays.get(i))); + Assert.assertNull(Array.get(arrays.get(i), 0)); + } + } + + @Test + public void testReadableRelocatedIndexClassLiteralsAndArrays() { + List> expected = Arrays.asList(Index.class, Index.IdWithExpiredTime.class); + Object classes = this.read("index_classes"); + Assert.assertEquals(expected, classes); + Assert.assertEquals(expected, roundTrip(classes)); + Object indexes = this.read("index_array"); + Assert.assertEquals(Index[].class, indexes.getClass()); + Assert.assertArrayEquals(new Index[]{null}, (Index[]) indexes); + Assert.assertArrayEquals((Index[]) indexes, (Index[]) roundTrip(indexes)); + Object expires = this.read("expiry_id_array"); + Assert.assertEquals(Index.IdWithExpiredTime[].class, expires.getClass()); + Assert.assertArrayEquals(new Index.IdWithExpiredTime[]{null}, (Index.IdWithExpiredTime[]) expires); + Assert.assertArrayEquals((Index.IdWithExpiredTime[]) expires, + (Index.IdWithExpiredTime[]) roundTrip(expires)); + } + + @Test + public void testLegacyArrayDescriptorDimensionBoundary() { + String legacy = "org.apache.hugegraph.backend.id.Id"; + Assert.assertEquals(Id.class, LegacyClassNames.lookup(legacy)); + Assert.assertEquals(Id[].class, LegacyClassNames.lookup("[L" + legacy + ";")); + Class limit = LegacyClassNames.lookup("[".repeat(255) + "L" + legacy + ";"); + int dimensions = 0; + while (limit.isArray()) { + dimensions++; + limit = limit.getComponentType(); + } + Assert.assertEquals(255, dimensions); + Assert.assertEquals(Id.class, limit); + Assert.assertNull(LegacyClassNames.lookup("[".repeat(256) + "L" + legacy + ";")); + Assert.assertNull(LegacyClassNames.lookup("[".repeat(5000) + "L" + legacy + ";")); + Assert.assertNull(LegacyClassNames.lookup("[Lexample.UserClass;")); + Assert.assertNull(LegacyClassNames.lookup("[I")); + } + + @Test + public void testOriginalUnsupportedInstancesKeepConstructorPolicy() { + for (String name : new String[]{"long_id", "string_id", "uuid_id", "edge_id", "binary_id", + "shard", "property_key", "vertex_label", "edge_label", + "index_label", "expiry_id", "unsupported_arrays_list"}) { + Assert.assertEquals(name, "false", this.fixtures.getProperty(name + ".baseline_readable")); + Assert.assertTrue(this.fixtures.getProperty(name + ".baseline_error") + .contains("missing no-arg constructor")); + // Reset failure state before and after a read, keeping independent + // fixtures independent without changing the instantiation strategy. + KryoUtil.kryo().reset(); + try { + KryoException error = Assert.assertThrows(KryoException.class, + () -> this.decode(name)); + Assert.assertTrue(name + ": " + error.getMessage(), + error.getMessage().contains("missing no-arg constructor")); + } finally { + KryoUtil.kryo().reset(); + } + } + } + + private void assertValue(String name, Object expected) { + Object decoded = this.read(name); + Assert.assertEquals(expected, decoded); + // Java API names may change. New writes need semantic compatibility, + // rather than continuing to emit removed core class names. + Assert.assertEquals(expected, roundTrip(decoded)); + } + + private Object read(String name) { + Assert.assertEquals(name, "true", this.fixtures.getProperty(name + ".baseline_readable")); + return this.decode(name); + } + + private Object decode(String name) { + BytesBuffer reader = BytesBuffer.wrap(Bytes.fromHex(this.fixtures.getProperty(name + ".hex"))); + Object decoded = reader.readProperty(DataType.OBJECT); + Assert.assertEquals(0, reader.remaining()); + return decoded; + } + + private static Object roundTrip(Object value) { + BytesBuffer writer = BytesBuffer.allocate(128); + writer.writeProperty(DataType.OBJECT, value); + return BytesBuffer.wrap(writer.bytes()).readProperty(DataType.OBJECT); + } + + private static Userdata expectedUserdata() { + Userdata userdata = new Userdata(); + userdata.put("tag", "legacy"); + userdata.put("count", 7); + userdata.put(Userdata.CREATE_TIME, new Date(1609459200123L)); + return userdata; + } + + private static List> expectedClasses() { + return new ArrayList<>(Arrays.asList(IdGenerator.LongId.class, + IdGenerator.StringId.class, IdGenerator.UuidId.class, + EdgeId.class, BinaryId.class, Shard.class, PropertyKey.class, + VertexLabel.class, EdgeLabel.class, IndexLabel.class)); + } + + private static Class nestedClass(Class owner, String name) { + return Arrays.stream(owner.getDeclaredClasses()) + .filter(type -> type.getSimpleName().equals(name)) + .findFirst().orElseThrow(AssertionError::new); + } + + private static void assertColumn(Object value) { + Assert.assertEquals(BackendColumn.class, value.getClass()); + BackendColumn column = (BackendColumn) value; + Assert.assertArrayEquals(new byte[]{1, 2}, column.name); + Assert.assertArrayEquals(new byte[]{3, 4}, column.value); + } + + private static void assertNested(Object value) { + Assert.assertTrue(value instanceof Map); + Map nested = (Map) value; + Assert.assertEquals(expectedClasses(), nested.get("classes")); + Assert.assertEquals(expectedUserdata(), nested.get("metadata")); + Assert.assertEquals(Id[][].class, nested.get("ids").getClass()); + Assert.assertArrayEquals(new Id[][]{new Id[]{null}, new Id[0]}, (Id[][]) nested.get("ids")); + Assert.assertEquals(Condition.RelationType.GTE, nested.get("predicate")); + assertColumn(nested.get("column")); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/id/IdCompatibilityTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/id/IdCompatibilityTest.java new file mode 100644 index 0000000000..96eff3ba4b --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/id/IdCompatibilityTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.id; + +import java.util.UUID; + +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.util.StringEncoding; +import org.junit.Assert; +import org.junit.Test; + +public class IdCompatibilityTest { + + @Test + public void testNumericIdsRejectTextAndNullWithoutParsing() { + Id id = IdGenerator.of(42L); + Assert.assertFalse(id.equals(null)); + Assert.assertFalse(id.equals("42")); + Assert.assertFalse(id.equals("42.0")); + Assert.assertFalse(id.equals("not-a-number")); + Assert.assertFalse(id.equals(IdGenerator.of("42"))); + Id same = IdGenerator.of(new byte[]{0, 0, 0, 0, 0, 0, 0, 42}, Id.IdType.LONG); + Assert.assertEquals(id, same); + Assert.assertEquals(id.hashCode(), same.hashCode()); + } + + @Test + public void testUtf8IdsAgreeAcrossStringAndByteRepresentations() { + String text = "北京`>vertex"; + Id fromString = IdGenerator.of(text); + Id fromBytes = IdGenerator.of(StringEncoding.encode(text), Id.IdType.STRING); + Assert.assertEquals(fromString, fromBytes); + Assert.assertEquals(fromBytes, fromString); + Assert.assertEquals(fromString.hashCode(), fromBytes.hashCode()); + Assert.assertEquals(0, fromString.compareTo(fromBytes)); + Assert.assertEquals(0, fromBytes.compareTo(fromString)); + Assert.assertEquals(text, fromBytes.asObject()); + Assert.assertArrayEquals(StringEncoding.encode(text), fromString.asBytes()); + } + + @Test + public void testStoredIdsPreserveTypesAndEscapedEdgeParts() { + Id[] ids = { + IdGenerator.of(Long.MIN_VALUE), + IdGenerator.of("北京`>vertex"), + IdGenerator.of(UUID.fromString("00112233-4455-6677-8899-aabbccddeeff")), + new EdgeId(IdGenerator.of("owner>vertex"), Directions.OUT, + IdGenerator.of(1), IdGenerator.of(2), "value>with`escape", + IdGenerator.of(42)) + }; + for (Id id : ids) { + Id stored = IdUtil.readStoredString(IdUtil.writeStoredString(id)); + Assert.assertEquals(id.type(), stored.type()); + Assert.assertEquals(id, stored); + Assert.assertEquals(id.hashCode(), stored.hashCode()); + } + Assert.assertEquals(Directions.OUT, EdgeId.directionFromCode(HugeType.EDGE_OUT.code())); + Assert.assertEquals(Directions.IN, EdgeId.directionFromCode(HugeType.EDGE_IN.code())); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/query/SharedQueryTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/query/SharedQueryTest.java new file mode 100644 index 0000000000..f73e6f416f --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/query/SharedQueryTest.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.query; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.hugegraph.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.HugeKeys; +import org.junit.Assert; +import org.junit.Test; + +public class SharedQueryTest { + + @Test + public void testOffsetAdvancesOnlyByCurrentBatchSize() { + Query query = new Query(HugeType.VERTEX); + query.offset(5L); + query.limit(2L); + Assert.assertTrue(query.skipOffsetIfNeeded( + new LinkedHashSet<>(Arrays.asList(1, 2))).isEmpty()); + Assert.assertEquals(2L, query.actualOffset()); + Assert.assertTrue(query.skipOffsetIfNeeded( + new LinkedHashSet<>(Arrays.asList(3, 4))).isEmpty()); + Assert.assertEquals(4L, query.actualOffset()); + Assert.assertEquals(new LinkedHashSet<>(Arrays.asList(6, 7)), + query.skipOffsetIfNeeded( + new LinkedHashSet<>(Arrays.asList(5, 6, 7)))); + Assert.assertEquals(5L, query.actualOffset()); + } + + @Test + public void testContradictoryIntersectionsStayEmpty() { + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.query(Condition.eq(HugeKeys.LABEL, 1)); + query.query(Condition.eq(HugeKeys.LABEL, 2)); + query.query(Condition.in(HugeKeys.LABEL, Arrays.asList(2, 3))); + Assert.assertNull(query.condition(HugeKeys.LABEL)); + + ConditionQuery emptyFirst = new ConditionQuery(HugeType.VERTEX); + emptyFirst.query(Condition.in(HugeKeys.LABEL, Collections.emptyList())); + emptyFirst.query(Condition.in(HugeKeys.LABEL, Arrays.asList(2, 3))); + Assert.assertNull(emptyFirst.condition(HugeKeys.LABEL)); + } + + @Test + public void testSingleIdAndCopy() { + Id id = IdGenerator.of(123L); + IdQuery.OneIdQuery query = new IdQuery.OneIdQuery(HugeType.VERTEX, id); + BaseVertex vertex = new BaseVertex(id); + Assert.assertTrue(query.test(vertex)); + Assert.assertFalse(query.test(new BaseVertex(IdGenerator.of(124L)))); + IdQuery.OneIdQuery copy = (IdQuery.OneIdQuery) query.copy(); + query.resetIds(); + Assert.assertEquals(0, query.idsSize()); + Assert.assertTrue(query.test(vertex)); + Assert.assertEquals(id, copy.id()); + Assert.assertEquals(1, copy.idsSize()); + } + + @Test + public void testRangeIndexValueConsumedOncePerProperty() { + Id key = IdGenerator.of(10L); + Id id = IdGenerator.of(123L); + PropertyKey property = new PropertyKey(null, key, "age"); + property.dataType(DataType.INT); + BaseVertex vertex = new BaseVertex(id); + vertex.addProperty(property, 25); + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.query(Condition.gte(key, 20)); + query.query(Condition.lte(key, 30)); + query.recordIndexValue(key, id, 25); + query.recordIndexValue(key, id, 17); + query.selectedIndexField(key); + Assert.assertTrue(query.test(vertex)); + Assert.assertEquals(1, query.getLeftIndexOfElement(id).size()); + Assert.assertEquals(Collections.singleton(17), + query.getLeftIndexOfElement(id).iterator().next() + .indexFieldValues()); + } + + @Test + public void testExplicitFilterAndFreshElements() { + BaseVertex vertex = new BaseVertex(IdGenerator.of(123L)); + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + AtomicInteger calls = new AtomicInteger(); + query.registerResultsFilter(element -> { + calls.incrementAndGet(); + return false; + }); + Assert.assertFalse(query.test(vertex)); + Assert.assertEquals(1, calls.get()); + vertex.fresh(true); + Assert.assertTrue(query.test(vertex)); + Assert.assertEquals(1, calls.get()); + vertex.fresh(false); + Assert.assertTrue(query.test(vertex, element -> true)); + Assert.assertEquals(1, calls.get()); + } + + @Test + public void testAggregateDescriptorRetainsNumericStrategy() { + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.aggregate(AggregateFunc.AVG, "age"); + byte[] encoded = query.bytes(); + Assert.assertTrue(new String(encoded, StandardCharsets.UTF_8) + .contains("\"aggregate\":{\"func\":\"AVG\",\"column\":\"age\"}")); + ConditionQuery decoded = ConditionQuery.fromBytes(encoded); + Assert.assertEquals(AggregateFunc.AVG, decoded.aggregateNotNull().func()); + Assert.assertEquals("age", decoded.aggregateNotNull().column()); + Assert.assertEquals(25D, decoded.aggregateNotNull() + .reduce(Arrays.asList(20, 30).iterator()) + .doubleValue(), 0D); + query.aggregate(AggregateFunc.COUNT, null); + decoded = ConditionQuery.fromBytes(query.bytes()); + Assert.assertTrue(decoded.aggregateNotNull().countAll()); + Assert.assertEquals(0L, decoded.aggregateNotNull().defaultValue()); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/serializer/OlapKeyTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/serializer/OlapKeyTest.java new file mode 100644 index 0000000000..7fb4eaecd0 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/serializer/OlapKeyTest.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.serializer; + +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.util.Bytes; +import org.junit.Assert; +import org.junit.Test; + +public class OlapKeyTest { + + @Test + public void testMergedKeyMatchesObservedRuntimeRequest() { + Assert.assertArrayEquals(Bytes.fromHex("080586313a616c696365"), + OlapKey.format(IdGenerator.of(5), IdGenerator.of("1:alice"))); + BytesBuffer key = BytesBuffer.wrap(OlapKey.format(IdGenerator.of(130), IdGenerator.of(1000))); + Assert.assertEquals(IdGenerator.of(130), key.readId()); + Assert.assertEquals(IdGenerator.of(1000), key.readId()); + Assert.assertEquals(0, key.remaining()); + } + + @Test + public void testValueIdentityUsesWholeVariableLengthPropertyId() { + byte[] observed = Bytes.fromHex("0563"); + Assert.assertTrue(OlapKey.matchesProperty(observed, IdGenerator.of(5))); + Assert.assertFalse(OlapKey.matchesProperty(observed, IdGenerator.of(8))); + byte[] largeProperty = BytesBuffer.allocate(16).writeVInt(130).writeVInt(99).bytes(); + Assert.assertTrue(OlapKey.matchesProperty(largeProperty, IdGenerator.of(130))); + Assert.assertFalse(OlapKey.matchesProperty(largeProperty, IdGenerator.of(1))); + Assert.assertFalse(OlapKey.matchesProperty(null, IdGenerator.of(5))); + Assert.assertFalse(OlapKey.matchesProperty(new byte[0], IdGenerator.of(5))); + Assert.assertFalse(OlapKey.matchesProperty(new byte[]{(byte) 0x81}, IdGenerator.of(5))); + Assert.assertFalse(OlapKey.matchesProperty(new byte[]{(byte) 0x80}, IdGenerator.of(5))); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/EdgeLabelMapTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/EdgeLabelMapTest.java new file mode 100644 index 0000000000..1d1ca47931 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/EdgeLabelMapTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.struct.schema; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper; +import org.junit.Assert; +import org.junit.Test; + +public class EdgeLabelMapTest { + + @Test + public void testSingleLinkMetadataRegardlessOfOrder() throws Exception { + // Exact field shapes emitted by the pre-consolidation Server JsonUtil. + Map wire = map("{\"id\":3,\"name\":\"knows\",\"links\":[{\"1\":2}]," + + "\"sourceLabel\":\"1\",\"targetLabel\":\"2\"}"); + EdgeLabel decoded = EdgeLabel.fromMap(wire, null); + Assert.assertEquals(Collections.singleton(Pair.of(IdGenerator.of(1), IdGenerator.of(2))), + decoded.links()); + Map endpointsFirst = new LinkedHashMap<>(); + endpointsFirst.put(EdgeLabel.P.SOURCE_LABEL, wire.get(EdgeLabel.P.SOURCE_LABEL)); + endpointsFirst.put(EdgeLabel.P.TARGET_LABEL, wire.get(EdgeLabel.P.TARGET_LABEL)); + endpointsFirst.putAll(wire); + Assert.assertEquals(decoded.links(), EdgeLabel.fromMap(endpointsFirst, null).links()); + } + + @Test + public void testLegacyEndpointsWithoutLinks() throws Exception { + Map wire = map("{\"id\":3,\"name\":\"knows\",\"sourceLabel\":\"1\"," + + "\"targetLabel\":\"2\"}"); + EdgeLabel decoded = EdgeLabel.fromMap(wire, null); + Assert.assertEquals(IdGenerator.of(1), decoded.sourceLabel()); + Assert.assertEquals(IdGenerator.of(2), decoded.targetLabel()); + Assert.assertEquals(1, decoded.links().size()); + } + + @Test + public void testMultiLinksAcceptConsistentRedundantEndpoints() throws Exception { + Map wire = map("{\"id\":3,\"name\":\"knows\",\"links\":[{\"1\":2},{\"2\":4}]," + + "\"sourceLabel\":\"1\",\"targetLabel\":\"2\"}"); + EdgeLabel decoded = EdgeLabel.fromMap(wire, null); + Assert.assertEquals(2, decoded.links().size()); + Assert.assertTrue(decoded.checkLinkEqual(IdGenerator.of(1), IdGenerator.of(2))); + Assert.assertTrue(decoded.checkLinkEqual(IdGenerator.of(2), IdGenerator.of(4))); + } + + @Test + public void testConflictingEndpointsRejected() throws Exception { + Map wire = map("{\"id\":3,\"name\":\"knows\",\"links\":[{\"1\":2}]," + + "\"sourceLabel\":\"1\",\"targetLabel\":\"4\"}"); + IllegalArgumentException error = Assert.assertThrows(IllegalArgumentException.class, + () -> EdgeLabel.fromMap(wire, null)); + Assert.assertTrue(error.getMessage().contains("conflict")); + } + + @Test + public void testIncompleteEndpointsRejected() throws Exception { + Map wire = map("{\"id\":3,\"name\":\"knows\",\"sourceLabel\":\"1\"}"); + Assert.assertThrows(IllegalArgumentException.class, () -> EdgeLabel.fromMap(wire, null)); + } + + @Test + public void testMalformedLinksRejected() throws Exception { + for (String value : new String[]{"null", "{}", "[{}]", "[{\"1\":null}]", + "[{\"invalid\":2}]"}) { + Map wire = map("{\"id\":3,\"name\":\"knows\",\"links\":" + value + "}"); + Assert.assertThrows(IllegalArgumentException.class, () -> EdgeLabel.fromMap(wire, null)); + } + } + + @SuppressWarnings("unchecked") + private static Map map(String json) throws Exception { + return new ObjectMapper().readValue(json, LinkedHashMap.class); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/OrderedSchemaFieldsTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/OrderedSchemaFieldsTest.java new file mode 100644 index 0000000000..2937e182ec --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/OrderedSchemaFieldsTest.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.struct.schema; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.SplicingIdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.query.IdQuery; +import org.apache.hugegraph.structure.BaseEdge; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper; +import org.junit.Assert; +import org.junit.Test; + +public class OrderedSchemaFieldsTest { + + @Test + public void testPrimaryKeyOrderDrivesVertexIdAndQuery() throws Exception { + VertexLabel label = VertexLabel.fromMap(map("{\"id\":1,\"name\":\"person\"," + + "\"idStrategy\":\"PRIMARY_KEY\"," + + "\"primaryKeys\":[2,17]}"), null); + Assert.assertEquals(Arrays.asList(id(2), id(17)), label.primaryKeys()); + BaseVertex vertex = new BaseVertex(null, label); + vertex.addProperty(key(17), "first"); + vertex.addProperty(key(2), "second"); + Assert.assertEquals(Arrays.asList("second", "first"), vertex.primaryValues()); + Assert.assertEquals("second!first", vertex.name()); + Id expected = IdGenerator.of("1:second!first"); + vertex.id(SplicingIdGenerator.instance().generate(vertex)); + Assert.assertEquals(expected, vertex.id()); + IdQuery query = new IdQuery(HugeType.VERTEX); + query.query(expected); + Assert.assertTrue(query.test(vertex)); + } + + @Test + public void testSortKeyOrderDrivesEdgeIdAndQuery() throws Exception { + EdgeLabel label = EdgeLabel.fromMap(map("{\"id\":3,\"name\":\"knows\"," + + "\"sortKeys\":[2,17],\"links\":[{\"1\":2}]}"), null); + Assert.assertEquals(Arrays.asList(id(2), id(17)), label.sortKeys()); + BaseEdge edge = new BaseEdge(label, true); + edge.addProperty(key(17), "first"); + edge.addProperty(key(2), "second"); + edge.vertices(true, new BaseVertex(id(1)), new BaseVertex(id(2))); + edge.assignId(); + Assert.assertEquals(Arrays.asList("second", "first"), edge.sortValues()); + Assert.assertEquals("second!first", ((EdgeId) edge.id()).sortValues()); + Assert.assertTrue(Condition.eq(HugeKeys.SORT_VALUES, "second!first").test(edge)); + Assert.assertFalse(Condition.eq(HugeKeys.SORT_VALUES, "first!second").test(edge)); + } + + @Test + public void testWriterAcceptedRepeatedKeysAreNotSilentlyDiscarded() throws Exception { + VertexLabel vertex = VertexLabel.fromMap(map("{\"id\":1,\"name\":\"person\"," + + "\"primaryKeys\":[2,17,2]}"), null); + EdgeLabel edge = EdgeLabel.fromMap(map("{\"id\":3,\"name\":\"knows\"," + + "\"sortKeys\":[2,17,2]}"), null); + List expected = Arrays.asList(id(2), id(17), id(2)); + Assert.assertEquals(expected, vertex.primaryKeys()); + Assert.assertEquals(expected, edge.sortKeys()); + } + + private static Id id(int value) { + return IdGenerator.of(value); + } + + private static PropertyKey key(int value) { + return new PropertyKey(null, id(value), "key" + value); + } + + @SuppressWarnings("unchecked") + private static Map map(String json) throws Exception { + return new ObjectMapper().readValue(json, Map.class); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/SchemaElementTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/SchemaElementTest.java new file mode 100644 index 0000000000..97c965f808 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/struct/schema/SchemaElementTest.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.struct.schema; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.type.define.SchemaStatus; +import org.apache.hugegraph.util.DateUtil; +import org.junit.Assert; +import org.junit.Test; + +public class SchemaElementTest { + + private static final String CREATE_TIME = "2026-05-14 10:11:12.345"; + + @Test + public void testCreateTimeNormalizationAtSharedBoundary() { + PropertyKey key = new PropertyKey(null, IdGenerator.of(1), "created"); + key.userdata(Userdata.CREATE_TIME, CREATE_TIME); + Assert.assertEquals(DateUtil.parse(CREATE_TIME), + key.userdata().get(Userdata.CREATE_TIME)); + + Date date = DateUtil.now(); + key.userdata(Userdata.CREATE_TIME, date); + Assert.assertSame(date, key.userdata().get(Userdata.CREATE_TIME)); + key.userdata(Userdata.CREATE_TIME, ""); + Assert.assertEquals("", key.userdata().get(Userdata.CREATE_TIME)); + key.userdata("note", CREATE_TIME); + Assert.assertEquals(CREATE_TIME, key.userdata().get("note")); + } + + @Test + public void testPersistedSchemaUserdataRestoresDate() { + Map userdata = new HashMap<>(); + userdata.put(Userdata.CREATE_TIME, CREATE_TIME); + userdata.put("count", 42); + Map serialized = new HashMap<>(); + serialized.put(VertexLabel.P.ID, 1); + serialized.put(VertexLabel.P.NAME, "person"); + serialized.put(VertexLabel.P.STATUS, SchemaStatus.CREATED.string()); + serialized.put(VertexLabel.P.USERDATA, userdata); + + VertexLabel label = VertexLabel.fromMap(serialized, null); + Assert.assertEquals(DateUtil.parse(CREATE_TIME), + label.userdata().get(Userdata.CREATE_TIME)); + Assert.assertEquals(42, label.userdata().get("count")); + Assert.assertEquals(SchemaStatus.CREATED, label.status()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidCreateTimeRejected() { + Userdata userdata = new Userdata(); + userdata.put(Userdata.CREATE_TIME, "not-a-date"); + } + + @Test(expected = IllegalArgumentException.class) + public void testNullBulkUserdataRejected() { + new PropertyKey(null, IdGenerator.of(1), "created").userdata((Userdata) null); + } + + @Test + public void testCopyPreservesIdentityAndStatus() { + PropertyKey key = new PropertyKey(null, IdGenerator.of(1), "created"); + key.userdata("note", "unchanged"); + key.status(SchemaStatus.CREATING); + SchemaElement copy = key.copy(); + Assert.assertNotSame(key, copy); + Assert.assertEquals(key, copy); + Assert.assertEquals(key.hashCode(), copy.hashCode()); + Assert.assertEquals(key.status(), copy.status()); + Assert.assertEquals(key.userdata(), copy.userdata()); + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedElementTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedElementTest.java new file mode 100644 index 0000000000..2cf661aa02 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedElementTest.java @@ -0,0 +1,260 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.structure; + +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.query.Condition; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.Userdata; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IdStrategy; +import org.junit.Assert; +import org.junit.Test; + +public class SharedElementTest { + + @Test + public void testSingleUpdateCallbackSeesPreviousValue() { + BaseVertex vertex = vertex(1); + PropertyKey key = key(Cardinality.SINGLE); + vertex.addProperty(key, "before"); + AtomicBoolean notified = new AtomicBoolean(); + vertex.addProperty(key, "after", BaseProperty::new, property -> { + Assert.assertEquals("before", vertex.getPropertyValue(key.id())); + Assert.assertEquals("after", property.value()); + notified.set(true); + }, property -> Assert.fail("Single update notified after replacement")); + Assert.assertTrue(notified.get()); + Assert.assertEquals("after", vertex.getPropertyValue(key.id())); + } + + @Test + public void testCollectionUpdateSharesPropertyAndNotifiesAfterMutation() { + BaseVertex vertex = vertex(1); + PropertyKey key = key(Cardinality.SET); + BaseProperty property = vertex.addProperty(key, "first"); + vertex.addProperty(key, Arrays.asList("first", "second"), BaseProperty::new, + value -> Assert.fail("Collection invoked single callback"), value -> { + Assert.assertSame(property, value); + Assert.assertEquals(2, ((Collection) value.value()).size()); + }); + Assert.assertSame(property, vertex.getProperty(key.id())); + } + + @Test + public void testCloneStateAndCopyPropertyMapAreIndependent() throws Exception { + BaseVertex original = vertex(1); + PropertyKey key = key(Cardinality.SINGLE); + original.addProperty(key, "original"); + BaseVertex copy = (BaseVertex) original.clone(); + copy.copyProperties(original); + copy.removed(true); + copy.expiredTime(100); + copy.addProperty(key, "replacement"); + Assert.assertFalse(original.removed()); + Assert.assertEquals(0, original.expiredTime()); + Assert.assertEquals("original", original.getPropertyValue(key.id())); + Assert.assertEquals("replacement", copy.getPropertyValue(key.id())); + } + + @Test + public void testSwitchOwnerPreservesSharedPropertiesAndOriginalDirection() { + EdgeLabel label = new EdgeLabel(null, IdGenerator.of(3), "link"); + BaseVertex source = vertex(1); + BaseVertex target = vertex(2); + BaseEdge original = new BaseEdge(label, true); + original.vertices(true, source, target); + original.name(""); + original.assignId(); + PropertyKey key = key(Cardinality.SINGLE); + original.addProperty(key, "value"); + BaseEdge reverse = original.switchOwner(); + Assert.assertTrue(original.isOutEdge()); + Assert.assertFalse(reverse.isOutEdge()); + Assert.assertEquals(source.id(), original.ownerVertexId()); + Assert.assertEquals(target.id(), reverse.ownerVertexId()); + Assert.assertSame(original.getProperty(key.id()), reverse.getProperty(key.id())); + reverse.resetProperties(); + Assert.assertTrue(original.hasProperty(key.id())); + Assert.assertFalse(reverse.hasProperty(key.id())); + } + + @Test + public void testLazyPropertyReadsAreUsedByValueMapAndEncoding() { + BaseVertex vertex = vertex(1); + PropertyKey key = key(Cardinality.SINGLE); + BaseProperty lazy = new BaseProperty(key, null) { + @Override + public String value() { + return "loaded"; + } + }; + vertex.addProperty(lazy); + Assert.assertEquals("loaded", vertex.getPropertiesMap().get(key.id())); + Assert.assertEquals(key.serialValue("loaded", true), lazy.serialValue(true)); + Assert.assertTrue(Condition.eq(key.id(), "loaded").test(vertex)); + } + + @Test + public void testQueryDoesNotLoadPropertiesOrInsertDefaultsImplicitly() { + BaseVertex vertex = vertex(1); + PropertyKey key = key(Cardinality.SINGLE); + key.userdata(Userdata.DEFAULT_VALUE, "default"); + vertex.schemaLabel().property(key.id()); + vertex.propLoaded(false); + Assert.assertFalse(Condition.eq(key.id(), "default").test(vertex)); + Assert.assertFalse(vertex.propLoaded()); + Assert.assertFalse(vertex.defaultValueUpdated()); + + // Engine accessors explicitly load backend data before updating defaults. + vertex.propLoaded(true); + vertex.updateDefaultValues(id -> key); + Assert.assertTrue(Condition.eq(key.id(), "default").test(vertex)); + Assert.assertTrue(vertex.defaultValueUpdated()); + vertex.addProperty(key, "explicit"); + vertex.updateDefaultValues(id -> key); + Assert.assertEquals("explicit", vertex.getPropertyValue(key.id())); + } + + @Test + public void testFreshPropertyMapsCannotAffectOtherElements() throws Exception { + BaseVertex first = vertex(1); + BaseVertex second = vertex(2); + BaseVertex clonedEmpty = (BaseVertex) first.clone(); + PropertyKey key = key(Cardinality.SINGLE); + Assert.assertNull(first.removeProperty(key.id())); + first.properties().put(BaseElement.intFromId(key.id()), new BaseProperty<>(key, "first")); + Assert.assertEquals("first", first.getPropertyValue(key.id())); + Assert.assertFalse(second.hasProperties()); + Assert.assertFalse(clonedEmpty.hasProperties()); + second.properties().put(BaseElement.intFromId(key.id()), new BaseProperty<>(key, "second")); + first.properties().clear(); + Assert.assertEquals("second", second.getPropertyValue(key.id())); + Assert.assertFalse(clonedEmpty.hasProperties()); + BaseVertex copied = (BaseVertex) second.clone(); + copied.copyProperties(second); + copied.properties().clear(); + Assert.assertEquals("second", second.getPropertyValue(key.id())); + } + + @Test + public void testSharedPrimaryNameUsesReservedValueContract() { + PropertyKey key = key(Cardinality.SINGLE); + VertexLabel label = new VertexLabel(null, IdGenerator.of(10), "person"); + label.idStrategy(IdStrategy.PRIMARY_KEY); + label.primaryKeys(key.id()); + BaseVertex vertex = new BaseVertex(null, label); + vertex.addProperty(key, ""); + Assert.assertThrows(IllegalArgumentException.class, vertex::name); + for (char prefix = 0; prefix <= 3; prefix++) { + vertex.addProperty(key, prefix + "value"); + Assert.assertThrows(IllegalArgumentException.class, vertex::name); + } + vertex.addProperty(key, "a!b"); + Assert.assertEquals("a`!b", vertex.name()); + } + + @Test + public void testSharedEdgeNamePreservesSortValueNormalization() { + PropertyKey key = key(Cardinality.SINGLE); + EdgeLabel label = new EdgeLabel(null, IdGenerator.of(3), "link"); + BaseEdge edge = new BaseEdge(null, label); + Assert.assertEquals("", edge.name()); + label.sortKeys(key.id()); + edge.name(null); + edge.addProperty(key, ""); + Assert.assertEquals("", edge.name()); + edge.name(null); + edge.addProperty(key, "a!b"); + Assert.assertEquals("a`!b", edge.name()); + edge.name(null); + edge.addProperty(key, "\u0000value"); + Assert.assertThrows(IllegalArgumentException.class, edge::name); + } + + @Test + public void testStandaloneUnknownSchemaFactoryRequiresNoSupplier() { + BaseVertex owner = vertex(1); + EdgeLabel label = new EdgeLabel(null, IdGenerator.of(3), "link"); + label.sourceLabel(IdGenerator.of(10)); + label.targetLabel(IdGenerator.of(11)); + BaseEdge edge = BaseEdge.createEdge(null, owner, true, label, "sort", IdGenerator.of(2)); + Assert.assertSame(owner, edge.ownerVertex()); + Assert.assertTrue(owner.schemaLabel().undefined()); + Assert.assertTrue(edge.otherVertex().schemaLabel().undefined()); + Assert.assertEquals(IdGenerator.of(10), owner.schemaLabel().id()); + Assert.assertEquals(IdGenerator.of(11), edge.otherVertex().schemaLabel().id()); + Assert.assertEquals("sort", edge.name()); + Assert.assertEquals(IdGenerator.of(2), edge.otherVertexId()); + } + + @Test + public void testUniqueAdjacencyUsesSharedEdgeIdEquality() { + BaseVertex owner = vertex(1); + BaseVertex other = vertex(2); + EdgeLabel label = new EdgeLabel(null, IdGenerator.of(3), "link"); + owner.resetEdges(true); + BaseEdge first = new BaseEdge(label, true); + first.vertices(true, owner, other); + first.name(""); + first.assignId(); + BaseEdge duplicate = first.clone(); + Assert.assertTrue(owner.addEdge(first)); + Assert.assertFalse(owner.addEdge(duplicate)); + Assert.assertEquals(1, owner.edges().size()); + Assert.assertSame(first, owner.removeEdge(duplicate)); + Assert.assertTrue(owner.edges().isEmpty()); + } + + @Test + public void testClassificationPreservesStorageAndEngineContracts() { + VertexLabel variables = new VertexLabel(null, IdGenerator.of(10), "~variables"); + BaseVertex stored = new BaseVertex(IdGenerator.of(1), variables); + BaseVertex engine = new BaseVertex(IdGenerator.of(1), variables, + BaseVertex.TypeContext.ENGINE); + Assert.assertEquals(HugeType.TASK, stored.type()); + Assert.assertEquals(HugeType.VERTEX, engine.type()); + + VertexLabel server = new VertexLabel(null, IdGenerator.of(11), "~server"); + stored.schemaLabel(server); + engine.schemaLabel(server); + Assert.assertEquals(HugeType.VERTEX, stored.type()); + Assert.assertEquals(HugeType.SERVER, engine.type()); + } + + private static BaseVertex vertex(long value) { + Id id = IdGenerator.of(value); + return new BaseVertex(id, new VertexLabel(null, IdGenerator.of(10), "person")); + } + + private static PropertyKey key(Cardinality cardinality) { + PropertyKey key = new PropertyKey(null, IdGenerator.of(1), "name"); + key.dataType(DataType.TEXT); + key.cardinality(cardinality); + return key; + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedIndexTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedIndexTest.java new file mode 100644 index 0000000000..643fe4939e --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/SharedIndexTest.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.structure; + +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IndexType; +import org.junit.Assert; +import org.junit.Test; + +public class SharedIndexTest { + + @Test + public void testLegacyIndexIdAndHashBytes() { + // Fixed Server bytes from compatibility/2f827d6e8 fixtures, not a + // round-trip assertion using the same writer and reader. + Assert.assertArrayEquals(new byte[]{(byte) 160, 0, 0, 0, 3, (byte) 128, 0, 0, 7}, + Index.formatIndexId(HugeType.RANGE_INT_INDEX, + id(3), 7).asBytes()); + Assert.assertArrayEquals(new byte[]{(byte) 162, 0, 0, 0, 3, + (byte) 128, 0, 0, 0, 0, 0, 0, 7}, + Index.formatIndexId(HugeType.RANGE_LONG_INDEX, + id(3), 7L).asBytes()); + // Frozen Server index-builder-contract.properties stores this hash. + Assert.assertArrayEquals("SI:F:224054a2".getBytes(StandardCharsets.UTF_8), + Index.formatIndexHashId(HugeType.SECONDARY_INDEX, id(15), + "long-field-".repeat(20)).asBytes()); + Assert.assertThrows(IllegalStateException.class, + () -> Index.formatIndexHashId(HugeType.RANGE_INT_INDEX, id(3), 7)); + } + + @Test + public void testLegacyRangeIdParsesWithSchemaType() { + IndexLabel label = label(null); + label.indexType(IndexType.RANGE_INT); + label.indexFields(id(2)); + HugeGraphSupplier graph = graph(label, 100); + Index parsed = Index.parseIndexId(graph, HugeType.RANGE_INT_INDEX, + new byte[]{(byte) 160, 0, 0, 0, 3, + (byte) 128, 0, 0, 7}); + Assert.assertSame(label, parsed.indexLabel()); + Assert.assertEquals(7, parsed.fieldValues()); + } + + @Test + public void testCloneResetKeepsEveryExpirationEntry() { + IndexLabel label = label(null); + Index original = new Index(graph(label, 100), label); + original.fieldValues("value"); + original.elementIds(id(1), 90); + original.elementIds(id(2), 95); + original.elementIds(id(3), 110); + Set expired = original.expiredElementIds(); + Assert.assertEquals(2, expired.size()); + + Index deletion = original.clone(); + Assert.assertEquals(original.id(), deletion.id()); + deletion.resetElementIds(); + for (Index.IdWithExpiredTime entry : expired) { + deletion.elementIds(entry.id(), entry.expiredTime()); + } + Assert.assertEquals(ids(1, 2), deletion.elementIds()); + Assert.assertEquals(ids(3), original.elementIds()); + Set copied = deletion.expiredElementIds(); + long[] times = copied.stream().mapToLong(Index.IdWithExpiredTime::expiredTime).toArray(); + Assert.assertArrayEquals(new long[]{90, 95}, times); + Assert.assertEquals(ids(3), original.elementIds()); + } + + @Test + public void testExpirationBoundaryAndTtl() { + IndexLabel label = label(null); + HugeGraphSupplier graph = graph(label, 100); + Index index = new Index(graph, label(graph)); + index.elementIds(id(1), 0); + index.elementIds(id(2), 99); + index.elementIds(id(3), 100); + index.elementIds(id(4), 101); + Assert.assertEquals(1, index.expiredElementIds().size()); + Assert.assertEquals(ids(1, 3, 4), index.elementIds()); + index.resetElementIds(); + index.elementIds(id(4), 101); + Assert.assertTrue(index.hasTtl()); + Assert.assertEquals(1, index.ttl()); + Assert.assertEquals(101, index.expiredTime()); + } + + @Test + public void testSystemIndexDoesNotAcquirePropertyTtl() { + HugeGraphSupplier graph = graph(label(null), 100); + Index index = new Index(graph, IndexLabel.label(HugeType.VERTEX)); + index.elementIds(id(1), 120); + Assert.assertFalse(index.hasTtl()); + Assert.assertEquals(120, index.expiredTime()); + } + + @Test + public void testWriteModeResetAndExpiration() { + IndexLabel label = label(null); + Index index = new Index(graph(label, 100), label, true); + index.elementIds(id(1), 99); + Assert.assertEquals(1, index.expiredElementIds().size()); + Assert.assertThrows(IllegalStateException.class, index::elementId); + index.elementIds(id(2), 150); + Index clone = index.clone(); + clone.resetElementIds(); + clone.elementIds(id(3), 160); + Assert.assertEquals(id(2), index.elementId()); + Assert.assertEquals(150, index.expiredTime()); + Assert.assertEquals(id(3), clone.elementId()); + Assert.assertEquals(160, clone.expiredTime()); + Assert.assertTrue(clone.expiredElementIds().isEmpty()); + } + + private static Id id(long value) { + return IdGenerator.of(value); + } + + private static Set ids(long... values) { + Set result = new LinkedHashSet<>(); + Arrays.stream(values).mapToObj(SharedIndexTest::id).forEach(result::add); + return result; + } + + private static IndexLabel label(HugeGraphSupplier graph) { + IndexLabel label = new IndexLabel(graph, id(3), "by_value"); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(id(1)); + label.indexType(IndexType.SECONDARY); + return label; + } + + private static HugeGraphSupplier graph(IndexLabel label, long now) { + final HugeGraphSupplier[] holder = new HugeGraphSupplier[1]; + holder[0] = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, args) -> { + switch (method.getName()) { + case "now": + return now; + case "indexLabel": + return label; + case "vertexLabel": + VertexLabel vertexLabel = new VertexLabel(holder[0], id(1), "person"); + vertexLabel.ttl(1000); + return vertexLabel; + case "propertyKey": + PropertyKey key = new PropertyKey(holder[0], id(2), "value"); + key.dataType(DataType.INT); + return key; + default: + throw new UnsupportedOperationException(method.getName()); + } + }); + return holder[0]; + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/builder/IndexBuilderTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/builder/IndexBuilderTest.java new file mode 100644 index 0000000000..775c261cee --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/structure/builder/IndexBuilderTest.java @@ -0,0 +1,284 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.structure.builder; + +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.query.MatchedIndex; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.EdgeLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.BaseEdge; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.type.define.WriteType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.EdgeLabelType; +import org.junit.Assert; +import org.junit.Test; + +public class IndexBuilderTest { + + @Test + public void testSearchIncludesOriginalTextAndIgnoresReservedSymbols() { + IndexBuilder builder = new IndexBuilder(supplier(), text -> Set.of("alpha", "beta", "\u0001", "\u0002")); + Assert.assertEquals(Set.of("alpha", "beta", "alpha beta"), builder.segmentWords("alpha beta")); + } + + @Test + public void testExplicitSearchWordsBypassAnalyzer() { + AtomicInteger calls = new AtomicInteger(); + IndexBuilder builder = new IndexBuilder(supplier(), text -> { + calls.incrementAndGet(); + return Set.of("analyzed"); + }); + Assert.assertEquals(Set.of("alpha", "beta"), builder.segmentWords("(alpha|beta|alpha)")); + Assert.assertEquals(Set.of("alpha"), builder.segmentWords("(alpha)")); + Assert.assertEquals(Set.of(""), builder.segmentWords("()")); + Assert.assertEquals(0, calls.get()); + } + + @Test + public void testSearchExpansionForCollectionIncludesJoinedText() { + HugeGraphSupplier graph = supplier(); + PropertyKey property = property(graph, 1, DataType.TEXT, Cardinality.LIST); + BaseVertex vertex = vertex(graph, property); + vertex.addProperty(property, List.of("alpha", "beta")); + IndexLabel label = index(graph, 1, IndexType.SEARCH, property); + IndexBuilder builder = new IndexBuilder(graph, text -> Set.of("alpha", "beta")); + Set words = new HashSet<>(); + builder.forEachIndex(vertex, label, index -> words.add(index.fieldValues())); + Assert.assertEquals(Set.of("alpha", "beta", "alpha beta"), words); + Assert.assertEquals("alpha beta", IndexBuilder.propertyValueToString(List.of("alpha", "beta"))); + } + + @Test + public void testNullablePrefixAndUniqueNullExpansion() { + HugeGraphSupplier graph = supplier(); + PropertyKey first = property(graph, 1, DataType.TEXT, Cardinality.SINGLE); + PropertyKey missing = property(graph, 2, DataType.TEXT, Cardinality.SINGLE); + PropertyKey last = property(graph, 3, DataType.TEXT, Cardinality.SINGLE); + BaseVertex vertex = vertex(graph, first, missing, last); + vertex.schemaLabel().nullableKeys(missing.id()); + vertex.addProperty(first, "first"); + vertex.addProperty(last, "last"); + IndexBuilder builder = new IndexBuilder(graph, text -> Set.of(text)); + IndexLabel secondary = index(graph, 1, IndexType.SECONDARY, first, missing, last); + List indexes = builder.buildIndex(vertex, secondary); + Assert.assertEquals(1, indexes.size()); + Assert.assertEquals("first", indexes.get(0).fieldValues()); + IndexLabel unique = index(graph, 2, IndexType.UNIQUE, first, missing, last); + Assert.assertEquals("first!\u0001!last", builder.buildIndex(vertex, unique).get(0).fieldValues()); + } + + @Test + public void testCollectionSecondaryExpansionPreservesDuplicateValuesAndExpiry() { + HugeGraphSupplier graph = supplier(); + PropertyKey property = property(graph, 1, DataType.INT, Cardinality.LIST); + BaseVertex vertex = vertex(graph, property); + vertex.addProperty(property, List.of(7, -1, 7)); + vertex.expiredTime(123L); + IndexLabel label = index(graph, 1, IndexType.SECONDARY, property); + List indexes = new ArrayList<>(); + new IndexBuilder(graph, text -> Set.of(text)).forEachIndex(vertex, label, indexes::add); + Assert.assertEquals(3, indexes.size()); + Assert.assertEquals(indexes.get(0).fieldValues(), indexes.get(2).fieldValues()); + Assert.assertNotEquals(indexes.get(0).fieldValues(), indexes.get(1).fieldValues()); + for (Index index : indexes) { + Assert.assertEquals(vertex.id(), index.elementId()); + Assert.assertEquals(123L, index.expiredTime()); + } + } + + @Test + public void testStoreRebuildIncludesParentIndexesAndPreservesSelectorOrderAndDuplicates() { + Map labels = new HashMap<>(); + Map indexes = new HashMap<>(); + HugeGraphSupplier graph = supplier(labels, indexes); + PropertyKey inherited = property(graph, 1, DataType.TEXT, Cardinality.SINGLE); + PropertyKey own = property(graph, 2, DataType.TEXT, Cardinality.SINGLE); + EdgeLabel parent = new EdgeLabel(graph, IdGenerator.of(3), "parent"); + parent.enableLabelIndex(false); + EdgeLabel child = new EdgeLabel(graph, IdGenerator.of(4), "child"); + child.edgeLabelType(EdgeLabelType.SUB); + child.fatherId(parent.id()); + child.enableLabelIndex(false); + labels.put(parent.id(), parent); + IndexLabel parentIndex = index(graph, 11, IndexType.SECONDARY, inherited); + parentIndex.baseType(HugeType.EDGE_LABEL); + parentIndex.baseValue(parent.id()); + IndexLabel childIndex = index(graph, 12, IndexType.SECONDARY, own); + childIndex.baseType(HugeType.EDGE_LABEL); + childIndex.baseValue(child.id()); + indexes.put(parentIndex.id(), parentIndex); + indexes.put(childIndex.id(), childIndex); + parent.indexLabels(parentIndex.id()); + child.indexLabels(childIndex.id()); + BaseEdge edge = new BaseEdge(new EdgeId(IdGenerator.of(1), Directions.OUT, parent.id(), child.id(), + "", IdGenerator.of(2)), child); + edge.isOutEdge(true); + edge.addProperty(inherited, "parent value"); + edge.addProperty(own, "child value"); + IndexBuilder builder = new IndexBuilder(graph, text -> Set.of(text)); + List rebuilt = builder.buildEdgeIndex(edge); + Assert.assertEquals(2, rebuilt.size()); + Assert.assertEquals(childIndex.id(), rebuilt.get(0).indexLabelId()); + Assert.assertEquals("child value", rebuilt.get(0).fieldValues()); + Assert.assertEquals(parentIndex.id(), rebuilt.get(1).indexLabelId()); + Assert.assertEquals("parent value", rebuilt.get(1).fieldValues()); + + child.indexLabels(parentIndex.id()); + List selected = new ArrayList<>(); + IndexBuilder.forEachIndexLabelId(edge, labels::get, selected::add); + List expected = new ArrayList<>(child.indexLabels()); + expected.addAll(parent.indexLabels()); + Assert.assertEquals(expected, selected); + Assert.assertEquals(2L, selected.stream().filter(parentIndex.id()::equals).count()); + Assert.assertEquals(3, builder.buildEdgeIndex(edge).size()); + } + + @Test + public void testOlapSelectorUsesProvidedStagedCandidates() { + HugeGraphSupplier graph = supplier(); + PropertyKey property = property(graph, 1, DataType.INT, Cardinality.SINGLE); + property.writeType(WriteType.OLAP_COMMON); + PropertyKey unrelated = property(graph, 2, DataType.INT, Cardinality.SINGLE); + BaseVertex vertex = new BaseVertex(IdGenerator.of(1), VertexLabel.OLAP_VL); + vertex.addProperty(property, 42); + IndexLabel staged = index(graph, 11, IndexType.RANGE_INT, property); + IndexLabel other = index(graph, 12, IndexType.RANGE_INT, unrelated); + List selected = new ArrayList<>(); + // The supplier has no index list; the caller's transaction candidates are authoritative. + IndexBuilder.forEachOlapIndexLabelId(vertex, List.of(other, staged), selected::add); + Assert.assertEquals(List.of(staged.id()), selected); + } + + @Test + public void testOlapSelectorRejectsZeroOrMultiplePropertiesBeforeCandidateTraversal() { + HugeGraphSupplier graph = supplier(); + BaseVertex vertex = new BaseVertex(IdGenerator.of(1), VertexLabel.OLAP_VL); + AtomicInteger traversals = new AtomicInteger(); + Iterable candidates = () -> { + traversals.incrementAndGet(); + return List.of().iterator(); + }; + assertInvalidOlap(vertex, candidates); + vertex.addProperty(property(graph, 1, DataType.INT, Cardinality.SINGLE), 42); + vertex.addProperty(property(graph, 2, DataType.INT, Cardinality.SINGLE), 43); + assertInvalidOlap(vertex, candidates); + Assert.assertEquals(0, traversals.get()); + } + + private static void assertInvalidOlap(BaseVertex vertex, Iterable candidates) { + try { + IndexBuilder.forEachOlapIndexLabelId(vertex, candidates, id -> Assert.fail("Unexpected selected index")); + Assert.fail("Olap selector must require exactly one property"); + } catch (IllegalArgumentException expected) { + Assert.assertTrue(expected.getMessage().contains("Expect only 1 property")); + } + } + + @Test + public void testMatchedIndexRetainsEngineEqualityAndReadOnlyLabels() { + HugeGraphSupplier graph = supplier(); + VertexLabel first = new VertexLabel(graph, IdGenerator.of(1), "first"); + VertexLabel second = new VertexLabel(graph, IdGenerator.of(2), "second"); + PropertyKey property = property(graph, 1, DataType.TEXT, Cardinality.SINGLE); + IndexLabel search = index(graph, 1, IndexType.SEARCH, property); + MatchedIndex match = new MatchedIndex(first, Set.of(search)); + MatchedIndex equal = new MatchedIndex(second, Set.of(search)); + Assert.assertEquals(match, equal); + Assert.assertEquals(match.hashCode(), equal.hashCode()); + Assert.assertTrue(match.containsSearchIndex()); + try { + match.indexLabels().clear(); + Assert.fail("Matched labels must remain read-only"); + } catch (UnsupportedOperationException expected) { + Assert.assertEquals(Set.of(search), match.indexLabels()); + } + } + + private static HugeGraphSupplier supplier() { + return supplier(Map.of(), Map.of()); + } + + private static HugeGraphSupplier supplier(Map labels, Map indexes) { + return (HugeGraphSupplier) Proxy.newProxyInstance(HugeGraphSupplier.class.getClassLoader(), + new Class[]{HugeGraphSupplier.class}, (proxy, method, args) -> { + switch (method.getName()) { + case "name": + case "toString": + return "index-builder-test"; + case "now": + return 0L; + case "edgeLabel": + return labels.get(args[0]); + case "indexLabel": + return indexes.get(args[0]); + case "hashCode": + return System.identityHashCode(proxy); + case "equals": + return proxy == args[0]; + default: + return null; + } + }); + } + + private static PropertyKey property(HugeGraphSupplier graph, int value, DataType type, Cardinality cardinality) { + PropertyKey property = new PropertyKey(graph, IdGenerator.of(value), "property" + value); + property.dataType(type); + property.cardinality(cardinality); + return property; + } + + private static BaseVertex vertex(HugeGraphSupplier graph, PropertyKey... properties) { + VertexLabel label = new VertexLabel(graph, IdGenerator.of(1), "vertex"); + for (PropertyKey property : properties) { + label.properties(Set.of(property.id())); + } + return new BaseVertex(IdGenerator.of(1), label); + } + + private static IndexLabel index(HugeGraphSupplier graph, int value, IndexType type, PropertyKey... fields) { + IndexLabel label = new IndexLabel(graph, IdGenerator.of(value), "index" + value); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(IdGenerator.of(1)); + label.indexType(type); + for (PropertyKey property : fields) { + label.indexField(property.id()); + } + return label; + } +} diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/type/SharedTypeCompatibilityTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/type/SharedTypeCompatibilityTest.java new file mode 100644 index 0000000000..a1f08ef3ea --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/type/SharedTypeCompatibilityTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.type; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.EdgeLabelType; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.type.define.SchemaStatus; +import org.apache.hugegraph.type.define.SerialEnum; +import org.junit.Assert; +import org.junit.Test; + +public class SharedTypeCompatibilityTest { + + @Test + public void testStoredTypeAndSchemaCodesRemainReadable() { + Assert.assertEquals(HugeType.VERTEX, HugeType.fromCode((byte) 101)); + Assert.assertEquals(HugeType.EDGE_OUT, HugeType.fromCode((byte) 130)); + Assert.assertEquals(HugeType.EDGE_IN, HugeType.fromCode((byte) 140)); + Assert.assertEquals(HugeType.OLAP, HugeType.fromCode((byte) 106)); + Assert.assertEquals(HugeType.UNIQUE_INDEX, HugeType.fromCode((byte) 178)); + Assert.assertEquals(HugeType.SYS_SCHEMA, HugeType.fromCode((byte) 250)); + Assert.assertEquals(HugeType.MAX_TYPE, HugeType.fromCode((byte) 255)); + Assert.assertEquals((byte) 211, HugeKeys.SUB_LABEL.code()); + Assert.assertEquals((byte) 250, HugeKeys.AGGREGATE_PROPERTIES.code()); + Assert.assertEquals(EdgeLabelType.GENERAL, + SerialEnum.fromCode(EdgeLabelType.class, (byte) 4)); + Assert.assertEquals(SchemaStatus.CLEARING, + SerialEnum.fromCode(SchemaStatus.class, (byte) 7)); + Assert.assertEquals(Cardinality.SET, + SerialEnum.fromCode(Cardinality.class, (byte) 3)); + Assert.assertEquals(Directions.IN, + SerialEnum.fromCode(Directions.class, (byte) 2)); + } + + @Test + public void testLazyAndConcurrentEnumRegistration() throws Exception { + // This extension does not call register() in a static initializer. + Assert.assertEquals(ExtensionType.VALUE, + SerialEnum.fromCode(ExtensionType.class, (byte) 42)); + ExecutorService executor = Executors.newFixedThreadPool(4); + try { + List> tasks = new ArrayList<>(); + for (int thread = 0; thread < 4; thread++) { + tasks.add(() -> { + for (int iteration = 0; iteration < 1000; iteration++) { + SerialEnum.register(Cardinality.class); + SerialEnum.register(ExtensionType.class); + Assert.assertEquals(Cardinality.LIST, + SerialEnum.fromCode(Cardinality.class, (byte) 2)); + Assert.assertEquals(ExtensionType.VALUE, + SerialEnum.fromCode(ExtensionType.class, (byte) 42)); + } + return null; + }); + } + List> results = executor.invokeAll(tasks, 10, TimeUnit.SECONDS); + for (Future result : results) { + Assert.assertFalse("Enum registration timed out", result.isCancelled()); + result.get(); + } + } finally { + executor.shutdownNow(); + } + } + + public enum ExtensionType implements SerialEnum { + VALUE; + + @Override + public byte code() { + return 42; + } + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/util/UnsafeUtilTest.java similarity index 53% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java rename to hugegraph-struct/src/test/java/org/apache/hugegraph/util/UnsafeUtilTest.java index 1c2950f11c..b948ea89b3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/exception/LimitExceedException.java +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/util/UnsafeUtilTest.java @@ -15,19 +15,30 @@ * limitations under the License. */ -package org.apache.hugegraph.exception; +package org.apache.hugegraph.util; -import org.apache.hugegraph.HugeException; +import org.apache.hugegraph.util.collection.IntSet; +import org.junit.Assert; +import org.junit.Test; -public class LimitExceedException extends HugeException { +import sun.misc.Unsafe; - private static final long serialVersionUID = 7384276720045597709L; +public class UnsafeUtilTest { - public LimitExceedException(String message) { - super(message); + @Test + public void testCollectionsShareUnsafeInstance() { + Assert.assertSame(UnsafeUtil.getUnsafe(), IntSet.UNSAFE); } - public LimitExceedException(String message, Object... args) { - super(message, args); + @Test + public void testNativeMemoryReadWrite() { + Unsafe unsafe = UnsafeUtil.getUnsafe(); + long address = unsafe.allocateMemory(Long.BYTES); + try { + unsafe.putLong(address, 0x0123456789abcdefL); + Assert.assertEquals(0x0123456789abcdefL, unsafe.getLong(address)); + } finally { + unsafe.freeMemory(address); + } } } diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyCodecFixtureWriter.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyCodecFixtureWriter.java.txt new file mode 100644 index 0000000000..f53b5b36af --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyCodecFixtureWriter.java.txt @@ -0,0 +1,181 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy 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.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.UUID; +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc; +import org.apache.hugegraph.backend.query.Condition; +import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry.BinaryId; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.HugeKeys; + +public class LegacyCodecFixtureWriter { + private static final String LICENSE = + "Licensed to the Apache Software Foundation (ASF) under one or more\n" + + "contributor license agreements. See the NOTICE file distributed with\n" + + "this work for additional information regarding copyright ownership.\n" + + "The ASF licenses this file to You under the Apache License, Version 2.0\n" + + "(the \"License\"); you may not use this file except in compliance with\n" + + "the License. You may obtain a copy of the License at\n\n" + + " http://www.apache.org/licenses/LICENSE-2.0\n\n" + + "Unless required by applicable law or agreed to in writing, software\n" + + "distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + "See the License for the specific language governing permissions and\n" + + "limitations under the License.\n"; + private static final Map HEX = new LinkedHashMap<>(); + + public static void main(String[] args) throws Exception { + Path output = Path.of(args[0]); + Files.createDirectories(output); + System.out.println("Writer loaded from " + BytesBuffer.class.getProtectionDomain() + .getCodeSource().getLocation()); + long[] values = {Long.MIN_VALUE, -16385L, -16384L, -129L, -128L, -1L, + 0L, 1L, 127L, 128L, 16383L, 16384L, Long.MAX_VALUE}; + for (long value : values) { + put("id.long." + value, BytesBuffer.allocate(64).writeId(IdGenerator.of(value))); + put("vlong." + value, BytesBuffer.allocate(64).writeVLong(value)); + } + int[] ints = {Integer.MIN_VALUE, -129, -1, 0, 127, 128, 16383, 16384, + Integer.MAX_VALUE}; + for (int value : ints) { + put("vint." + value, BytesBuffer.allocate(64).writeVInt(value)); + } + put("id.text", BytesBuffer.allocate(64).writeId(IdGenerator.of("alice"))); + put("id.unicode", BytesBuffer.allocate(64).writeId(IdGenerator.of("顶点😀"))); + for (int length : new int[]{1, 64, 65, 256, 257, 16384}) { + put("id.text.length." + length, + BytesBuffer.allocate(64).writeId(IdGenerator.of("x".repeat(length)))); + } + put("id.uuid", BytesBuffer.allocate(64).writeId(IdGenerator.of( + UUID.fromString("01234567-89ab-cdef-0123-456789abcdef")))); + Id edge = new EdgeId(IdGenerator.of("alice"), Directions.OUT, IdGenerator.of(3L), + IdGenerator.of(4L), "2026!x", IdGenerator.of(99L)); + put("edge.out", BytesBuffer.allocate(128).writeEdgeId(edge)); + edge = new EdgeId(IdGenerator.of(99L), Directions.IN, IdGenerator.of(3L), + IdGenerator.of(4L), "2026!x", IdGenerator.of("alice")); + put("edge.in", BytesBuffer.allocate(128).writeEdgeId(edge)); + scalar("BOOLEAN", DataType.BOOLEAN, true); + scalar("BYTE", DataType.BYTE, (byte) -7); + scalar("INT", DataType.INT, -123456); + scalar("LONG", DataType.LONG, Long.MIN_VALUE); + scalar("FLOAT", DataType.FLOAT, 1.25f); + scalar("DOUBLE", DataType.DOUBLE, -123.125d); + scalar("DATE", DataType.DATE, new Date(1609459200123L)); + scalar("TEXT", DataType.TEXT, "属性😀\u0000"); + scalar("BLOB", DataType.BLOB, new byte[]{0, -1, 1, 127, -128}); + scalar("UUID", DataType.UUID, + UUID.fromString("01234567-89ab-cdef-0123-456789abcdef")); + scalar("OBJECT", DataType.OBJECT, new ArrayList<>(Arrays.asList("legacy", 7, true))); + scalar("UNKNOWN", DataType.UNKNOWN, "legacy-object"); + scalar("OBJECT_UNSUPPORTED_COLLECTION", DataType.OBJECT, Arrays.asList("legacy", 7, true)); + PropertyKey propertyKey = new PropertyKey(null, IdGenerator.of(101L), "legacy"); + propertyKey.dataType(DataType.INT); + schemaProperty("single", propertyKey, Cardinality.SINGLE, 7); + schemaProperty("list", propertyKey, Cardinality.LIST, Arrays.asList(7, -1, 7)); + schemaProperty("set", propertyKey, Cardinality.SET, + new LinkedHashSet<>(Arrays.asList(7, -1))); + byte[] stringIndex = "label!alice".getBytes(StandardCharsets.UTF_8); + put("index.string", BytesBuffer.allocate(64).writeIndexId( + new BinaryId(stringIndex, null), HugeType.SECONDARY_INDEX)); + byte[] intIndex = {(byte) 160, 0, 0, 0, 3, (byte) 128, 0, 0, 7}; + put("index.int", BytesBuffer.allocate(64).writeIndexId( + new BinaryId(intIndex, null), HugeType.RANGE_INT_INDEX)); + byte[] longIndex = {(byte) 162, 0, 0, 0, 3, (byte) 128, 0, 0, 0, 0, 0, 0, 7}; + put("index.long", BytesBuffer.allocate(64).writeIndexId( + new BinaryId(longIndex, null), HugeType.RANGE_LONG_INDEX)); + StringBuilder encoded = new StringBuilder("# " + LICENSE.replace("\n", "\n# ") + "\n"); + for (Map.Entry fixture : HEX.entrySet()) { + String line = fixture.getKey() + "=" + fixture.getValue(); + for (int start = 0; start < line.length(); start += 100) { + int end = Math.min(start + 100, line.length()); + encoded.append(line, start, end); + if (end < line.length()) { + encoded.append('\\'); + } + encoded.append('\n'); + } + } + Files.writeString(output.resolve("core-codecs.hex"), encoded.toString().replaceAll("(?m)[ \t]+$", ""), + StandardCharsets.UTF_8); + + ConditionQuery query = new ConditionQuery(HugeType.VERTEX); + query.eq(HugeKeys.LABEL, IdGenerator.of(3L)); + query.query(Condition.gte(IdGenerator.of(11L), 18)); + query.query(Condition.in(IdGenerator.of(12L), Arrays.asList(20L, 30L))); + query.query(Condition.eq(IdGenerator.of(13L), new Date(1609459200123L))); + query.query(Condition.or(Condition.eq(IdGenerator.of(14L), "alice"), + Condition.eq(IdGenerator.of(14L), "bob"))); + query.offset(7); + query.limit(19); + writeQuery(output, "core-query.json.txt", query); + ConditionQuery edgeQuery = new ConditionQuery(HugeType.EDGE); + edgeQuery.eq(HugeKeys.OWNER_VERTEX, IdGenerator.of("alice")); + edgeQuery.eq(HugeKeys.DIRECTION, Directions.OUT); + edgeQuery.eq(HugeKeys.LABEL, IdGenerator.of(3L)); + edgeQuery.page("AQIDBA=="); + edgeQuery.limit(5); + writeQuery(output, "core-edge-query.json.txt", edgeQuery); + ConditionQuery countQuery = new ConditionQuery(HugeType.VERTEX); + countQuery.aggregate(AggregateFunc.COUNT, null); + writeQuery(output, "core-count-query.json.txt", countQuery); + ConditionQuery avgQuery = new ConditionQuery(HugeType.VERTEX); + avgQuery.eq(HugeKeys.LABEL, IdGenerator.of(3L)); + avgQuery.aggregate(AggregateFunc.AVG, "age"); + writeQuery(output, "core-avg-query.json.txt", avgQuery); + System.out.println("Generated " + HEX.size() + " byte fixtures and 4 query fixtures"); + } + + private static void writeQuery(Path output, String name, ConditionQuery query) + throws Exception { + String prolog = "/*\n" + LICENSE + "*/\n"; + String payload = new String(query.bytes(), StandardCharsets.UTF_8); + Files.writeString(output.resolve(name), prolog + payload + "\n", StandardCharsets.UTF_8); + } + + private static void schemaProperty(String name, PropertyKey key, + Cardinality cardinality, Object value) { + key.cardinality(cardinality); + put("schema." + name, BytesBuffer.allocate(64).writeProperty(key, value)); + } + + private static void scalar(String name, DataType type, Object value) { + BytesBuffer buffer = BytesBuffer.allocate(128); + buffer.writeProperty(type, value); + put("property." + name, buffer); + } + + private static void put(String name, BytesBuffer buffer) { + StringBuilder hex = new StringBuilder(); + for (byte value : buffer.bytes()) { + hex.append(String.format("%02x", value & 0xff)); + } + HEX.put(name, hex.toString()); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyKryoFixtureWriter.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyKryoFixtureWriter.java.txt new file mode 100644 index 0000000000..d2e75af556 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyKryoFixtureWriter.java.txt @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Array; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.query.Aggregate; +import org.apache.hugegraph.backend.query.Condition; +import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry.BinaryId; +import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.backend.store.Shard; +import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.schema.Userdata; +import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.structure.GraphType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Directions; + +public class LegacyKryoFixtureWriter { + private static final Map OUTPUT = new LinkedHashMap<>(); + + public static void main(String[] args) throws Exception { + System.out.println("Kryo fixture writer loaded from " + BytesBuffer.class + .getProtectionDomain().getCodeSource().getLocation()); + Id longId = IdGenerator.of(7L); + Id stringId = IdGenerator.of("legacy-id"); + Id uuidId = IdGenerator.of(UUID.fromString("01234567-89ab-cdef-0123-456789abcdef")); + Id edgeId = new EdgeId(longId, Directions.OUT, IdGenerator.of(3L), + IdGenerator.of(4L), "sort", stringId); + Object[] instances = {longId, stringId, uuidId, edgeId, + new BinaryId(new byte[]{1, 2, 3}, longId), + new Shard("start", "end", 12L), + new PropertyKey(null, IdGenerator.of(11L), "age"), + new VertexLabel(null, IdGenerator.of(12L), "person"), + new EdgeLabel(null, IdGenerator.of(13L), "knows"), + new IndexLabel(null, IdGenerator.of(14L), "by-age")}; + String[] names = {"long_id", "string_id", "uuid_id", "edge_id", "binary_id", "shard", + "property_key", "vertex_label", "edge_label", "index_label"}; + for (int i = 0; i < names.length; i++) { + capture(names[i], instances[i]); + } + capture("aggregate_func", Aggregate.AggregateFunc.AVG); + capture("relation_type", Condition.RelationType.GTE); + capture("condition_type", Condition.ConditionType.OR); + capture("query_order", Query.Order.DESC); + capture("query_order_type", Query.OrderType.ORDER_STRICT); + capture("optimized_type", ConditionQuery.OptimizedType.INDEX_FILTER); + capture("id_type", Id.IdType.UUID); + capture("graph_type_class", GraphType.class); + capture("id_array", new Id[]{null}); + capture("id_matrix", new Id[][]{new Id[]{null}, new Id[0]}); + capture("shard_array", new Shard[]{null}); + capture("schema_array", new PropertyKey[]{null}); + Userdata userdata = new Userdata(); + userdata.put("tag", "legacy"); + userdata.put("count", 7); + userdata.put(Userdata.CREATE_TIME, new Date(1609459200123L)); + capture("userdata", userdata); + BackendColumn column = BackendColumn.of(new byte[]{1, 2}, new byte[]{3, 4}); + capture("backend_column", column); + capture("backend_column_array", new BackendColumn[]{column, null}); + capture("backend_column_class", BackendColumn.class); + ArrayList> classes = new ArrayList<>(); + for (Object instance : instances) { + classes.add(instance.getClass()); + } + capture("class_list", classes); + String[] contracts = {"org.apache.hugegraph.type.Nameable", + "org.apache.hugegraph.type.Typeable", + "org.apache.hugegraph.type.Indexable", + "org.apache.hugegraph.type.Propertiable", + "org.apache.hugegraph.backend.id.IdUtil", + "org.apache.hugegraph.backend.id.SplicingIdGenerator", + "org.apache.hugegraph.schema.builder.SchemaBuilder", + "org.apache.hugegraph.backend.query.serializer.AbstractSerializerAdapter", + "org.apache.hugegraph.backend.query.serializer.QueryAdapter", + "org.apache.hugegraph.backend.query.serializer.QueryIdAdapter"}; + ArrayList> contractClasses = new ArrayList<>(); + for (String contract : contracts) { + contractClasses.add(Class.forName(contract)); + } + capture("contract_classes", contractClasses); + String[] schemaNames = {"org.apache.hugegraph.schema.SchemaElement$TaskWithSchema", + "org.apache.hugegraph.schema.PropertyKey$P", + "org.apache.hugegraph.schema.VertexLabel$P", + "org.apache.hugegraph.schema.EdgeLabel$P", + "org.apache.hugegraph.schema.IndexLabel$P", + "org.apache.hugegraph.schema.SchemaElement$P", + "org.apache.hugegraph.schema.PropertyKey$Builder", + "org.apache.hugegraph.schema.VertexLabel$Builder", + "org.apache.hugegraph.schema.EdgeLabel$Builder", + "org.apache.hugegraph.schema.IndexLabel$Builder"}; + ArrayList> schemaClasses = new ArrayList<>(); + ArrayList schemaArrays = new ArrayList<>(); + for (String schemaName : schemaNames) { + Class schemaClass = Class.forName(schemaName); + schemaClasses.add(schemaClass); + schemaArrays.add(Array.newInstance(schemaClass, 1)); + } + capture("schema_nested_classes", schemaClasses); + capture("schema_nested_arrays", schemaArrays); + capture("index_classes", new ArrayList<>(Arrays.asList( + org.apache.hugegraph.structure.HugeIndex.class, + org.apache.hugegraph.structure.HugeIndex.IdWithExpiredTime.class))); + capture("index_array", new org.apache.hugegraph.structure.HugeIndex[]{null}); + capture("expiry_id_array", new org.apache.hugegraph.structure.HugeIndex.IdWithExpiredTime[]{null}); + capture("expiry_id", new org.apache.hugegraph.structure.HugeIndex.IdWithExpiredTime(longId, + 1609459260000L)); + Map nested = new LinkedHashMap<>(); + nested.put("classes", classes); + nested.put("metadata", userdata); + nested.put("ids", new Id[][]{new Id[]{null}, new Id[0]}); + nested.put("predicate", Condition.RelationType.GTE); + nested.put("column", column); + capture("nested", nested); + capture("unsupported_arrays_list", Arrays.asList("legacy", 7, true)); + String source = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = source.substring(0, source.indexOf("*/") + 2); + StringBuilder text = new StringBuilder(license.replace("/*", "#") + .replace("*/", "#").replace(" *", "#")).append('\n'); + OUTPUT.forEach((key, value) -> append(text, key + "=" + value)); + Files.writeString(Path.of(args[0]).resolve("core-kryo-objects.properties"), text, + StandardCharsets.UTF_8); + } + + private static void capture(String name, Object value) { + BytesBuffer buffer = BytesBuffer.allocate(128); + buffer.writeProperty(DataType.OBJECT, value); + OUTPUT.put(name + ".hex", hex(buffer.bytes())); + try { + Object decoded = BytesBuffer.wrap(buffer.bytes()).readProperty(DataType.OBJECT); + OUTPUT.put(name + ".baseline_readable", "true"); + OUTPUT.put(name + ".baseline_type", decoded.getClass().getName()); + System.out.println(name + ": baseline readable " + decoded.getClass().getName()); + } catch (RuntimeException error) { + OUTPUT.put(name + ".baseline_readable", "false"); + OUTPUT.put(name + ".baseline_error", error.getClass().getName() + ": " + + error.getMessage().replace('\n', ' ')); + System.out.println(name + ": baseline fails " + error.getMessage().split("\\n")[0]); + } + } + + private static void append(StringBuilder output, String line) { + for (int start = 0; start < line.length(); start += 100) { + int end = Math.min(start + 100, line.length()); + output.append(line, start, end); + if (end < line.length()) { + output.append('\\'); + } + output.append('\n'); + } + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { + text.append(String.format("%02x", value & 0xff)); + } + return text.toString(); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt new file mode 100644 index 0000000000..abf389945d --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.serializer.BinarySerializer; +import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.type.define.HugeKeys; +import org.apache.hugegraph.backend.store.BackendEntry; +import org.apache.hugegraph.backend.store.BackendEntry.BackendColumn; +import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.schema.IndexLabel; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.schema.VertexLabel; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.structure.HugeIndex; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.type.define.Frequency; +import org.apache.hugegraph.type.define.IndexType; +import org.apache.hugegraph.type.define.WriteType; + +public class LegacyRowFixtureWriter { + private static final long NOW = 1609459200000L; + private static final long EXPIRY = NOW + 60000L; + private static final Map PROPERTIES = new HashMap<>(); + private static final Map VERTICES = new HashMap<>(); + private static final Map EDGES = new HashMap<>(); + private static final Map INDEXES = new HashMap<>(); + private static HugeGraph fixtureGraph; + private static FixtureSerializer fixtureSerializer; + private static final Map ROWS = new LinkedHashMap<>(); + + public static void main(String[] args) throws Exception { + HugeGraph graph = (HugeGraph) Proxy.newProxyInstance( + HugeGraph.class.getClassLoader(), new Class[]{HugeGraph.class}, + (proxy, method, values) -> { + switch (method.getName()) { + case "now": return NOW; + case "name": return "legacy-fixture"; + case "hugegraph": return proxy; + case "propertyKey": return PROPERTIES.get(((Id) values[0]).asLong()); + case "vertexLabel": + case "vertexLabelOrNone": return VERTICES.get(((Id) values[0]).asLong()); + case "edgeLabel": + case "edgeLabelOrNone": return EDGES.get(((Id) values[0]).asLong()); + case "indexLabel": return INDEXES.get(((Id) values[0]).asLong()); + default: throw new AssertionError("Unexpected graph call: " + method); + } + }); + fixtureGraph = graph; + PropertyKey single = property(graph, 1, "age", Cardinality.SINGLE); + PropertyKey list = property(graph, 2, "scores", Cardinality.LIST); + PropertyKey set = property(graph, 3, "groups", Cardinality.SET); + VertexLabel vertexLabel = new VertexLabel(graph, IdGenerator.of(4L), "person"); + vertexLabel.ttl(60000L); + vertexLabel.properties(single.id(), list.id(), set.id()); + VERTICES.put(4L, vertexLabel); + EdgeLabel edgeLabel = new EdgeLabel(graph, IdGenerator.of(5L), "knows"); + edgeLabel.ttl(60000L); + edgeLabel.frequency(Frequency.MULTIPLE); + edgeLabel.links(Pair.of(vertexLabel.id(), vertexLabel.id())); + edgeLabel.properties(single.id(), list.id(), set.id()); + EDGES.put(5L, edgeLabel); + HugeVertex source = new HugeVertex(graph, IdGenerator.of(1L), vertexLabel); + HugeVertex target = new HugeVertex(graph, IdGenerator.of(2L), vertexLabel); + fill(source, single, list, set); + source.expiredTime(EXPIRY); + FixtureSerializer serializer = new FixtureSerializer(); + fixtureSerializer = serializer; + System.out.println("Row writer loaded from " + BinarySerializer.class.getProtectionDomain() + .getCodeSource().getLocation()); + row("vertex", serializer.writeVertex(source)); + HugeEdge edge = new HugeEdge(graph, + new EdgeId(source.id(), Directions.OUT, edgeLabel.id(), edgeLabel.id(), + "2026!x", target.id()), edgeLabel); + edge.vertices(true, source, target); + fill(edge, single, list, set); + edge.expiredTime(EXPIRY); + row("edge.out", serializer.writeEdge(edge)); + row("edge.in", serializer.writeEdge(edge.switchOwner())); + PropertyKey olapKey = property(graph, 9, "rank", Cardinality.SINGLE); + olapKey.writeType(WriteType.OLAP_COMMON); + HugeVertex olap = new HugeVertex(graph, source.id(), VertexLabel.OLAP_VL); + olap.addProperty(olapKey, 42); + row("olap", serializer.writeVertex(olap)); + property(graph, 16L, "weight", Cardinality.SINGLE).dataType(DataType.LONG); + property(graph, 17L, "name", Cardinality.SINGLE).dataType(DataType.TEXT); + index("index.secondary", graph, serializer, 6L, IndexType.SECONDARY, "alice"); + index("index.int", graph, serializer, 7L, IndexType.RANGE_INT, 7); + index("index.long", graph, serializer, 8L, IndexType.RANGE_LONG, 7L); + VertexLabel timeless = new VertexLabel(graph, IdGenerator.of(10L), "timeless"); + timeless.properties(single.id(), list.id(), set.id()); + VERTICES.put(10L, timeless); + HugeVertex timelessVertex = new HugeVertex(graph, IdGenerator.of(3L), timeless); + fill(timelessVertex, single, list, set); + row("vertex.untimed", serializer.writeVertex(timelessVertex)); + EdgeLabel timelessEdgeLabel = new EdgeLabel(graph, IdGenerator.of(11L), "untimed"); + timelessEdgeLabel.links(Pair.of(vertexLabel.id(), vertexLabel.id())); + timelessEdgeLabel.properties(single.id(), list.id(), set.id()); + EDGES.put(11L, timelessEdgeLabel); + HugeEdge timelessEdge = new HugeEdge(graph, + new EdgeId(source.id(), Directions.OUT, timelessEdgeLabel.id(), timelessEdgeLabel.id(), + "", target.id()), timelessEdgeLabel); + timelessEdge.vertices(true, source, target); + fill(timelessEdge, single, list, set); + row("edge.untimed", serializer.writeEdge(timelessEdge)); + index("index.secondary.untimed", graph, serializer, 12L, + IndexType.SECONDARY, "alice", 10L); + index("index.int.untimed", graph, serializer, 13L, IndexType.RANGE_INT, 7, 10L); + index("index.long.untimed", graph, serializer, 14L, IndexType.RANGE_LONG, 7L, 10L); + index("index.hashed", graph, serializer, 15L, IndexType.SECONDARY, + "long-field-".repeat(20)); + HugeIndex systemIndex = new HugeIndex(graph, IndexLabel.label(HugeType.VERTEX)); + systemIndex.fieldValues(4L); + systemIndex.elementIds(source.id(), EXPIRY); + row("index.system", serializer.writeIndex(systemIndex)); + HugeIndex edgeSystemIndex = new HugeIndex(graph, IndexLabel.label(HugeType.EDGE)); + edgeSystemIndex.fieldValues(5L); + edgeSystemIndex.elementIds(edge.id(), EXPIRY); + row("index.system.edge", serializer.writeIndex(edgeSystemIndex)); + String producer = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = producer.substring(0, producer.indexOf("*/") + 2); + StringBuilder encoded = new StringBuilder(license.replace("/*", "#") + .replace("*/", "#").replace(" *", "#")).append('\n'); + encoded.append("now=").append(NOW).append('\n'); + encoded.append("expiry=").append(EXPIRY).append('\n'); + ROWS.forEach((key, value) -> encoded.append(key).append('=').append(value).append('\n')); + Files.createDirectories(Path.of(args[0])); + Files.writeString(Path.of(args[0]).resolve("core-rows.properties"), encoded, + StandardCharsets.UTF_8); + System.out.println("Generated 15 real legacy BinarySerializer rows"); + } + + private static PropertyKey property(HugeGraph graph, long id, String name, + Cardinality cardinality) { + PropertyKey key = new PropertyKey(graph, IdGenerator.of(id), name); + key.dataType(DataType.INT); + key.cardinality(cardinality); + PROPERTIES.put(id, key); + return key; + } + + private static void fill(HugeElement element, PropertyKey single, + PropertyKey list, PropertyKey set) { + element.addProperty(single, 7); + element.addProperty(list, Arrays.asList(7, -1, 7)); + element.addProperty(set, Arrays.asList(7, -1)); + } + + private static void index(String name, HugeGraph graph, BinarySerializer serializer, + long id, IndexType type, Object value) { + index(name, graph, serializer, id, type, value, 4L); + } + + private static void index(String name, HugeGraph graph, BinarySerializer serializer, + long id, IndexType type, Object value, long baseId) { + IndexLabel label = new IndexLabel(graph, IdGenerator.of(id), name); + label.indexType(type); + label.indexFields(IdGenerator.of(type == IndexType.RANGE_LONG ? 16L : + type == IndexType.SECONDARY ? 17L : 1L)); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(IdGenerator.of(baseId)); + INDEXES.put(id, label); + HugeIndex index = new HugeIndex(graph, label); + index.fieldValues(value); + index.elementIds(IdGenerator.of(1L), baseId == 4L ? EXPIRY : 0L); + row(name, serializer.writeIndex(index)); + } + + private static void row(String name, BackendEntry entry) { + if (entry.type().isVertex()) { + HugeVertex decoded = fixtureSerializer.readVertex(fixtureGraph, entry); + if (decoded.sizeOfProperties() != 3 || + !Integer.valueOf(7).equals(decoded.getPropertyValue(IdGenerator.of(1L)))) { + throw new AssertionError("Legacy vertex self-read failed: " + name); + } + } else if (entry.type().isEdge()) { + HugeEdge decoded = fixtureSerializer.readEdge(fixtureGraph, entry); + if (decoded.sizeOfProperties() != 3 || + !Integer.valueOf(7).equals(decoded.getPropertyValue(IdGenerator.of(1L)))) { + throw new AssertionError("Legacy edge self-read failed: " + name); + } + } else if (entry.type() == HugeType.OLAP) { + HugeVertex decoded = new HugeVertex(fixtureGraph, IdGenerator.of(1L), VERTICES.get(4L)); + fixtureSerializer.parseOlap(entry.columns().iterator().next().value, decoded); + if (!Integer.valueOf(42).equals(decoded.getPropertyValue(IdGenerator.of(9L)))) { + throw new AssertionError("Legacy OLAP self-read failed"); + } + } else if (entry.type().isIndex()) { + ConditionQuery query = new ConditionQuery(entry.type()); + if (name.equals("index.secondary") || name.equals("index.secondary.untimed")) { + query.eq(HugeKeys.FIELD_VALUES, "alice"); + } else if (name.equals("index.hashed")) { + query.eq(HugeKeys.FIELD_VALUES, "long-field-".repeat(20)); + } else if (name.equals("index.system")) { + query.eq(HugeKeys.FIELD_VALUES, 4L); + } else if (name.equals("index.system.edge")) { + query.eq(HugeKeys.FIELD_VALUES, 5L); + } + HugeIndex decoded = fixtureSerializer.readIndex(fixtureGraph, query, entry); + Id expectedElement = name.equals("index.system.edge") ? + new EdgeId(IdGenerator.of(1L), Directions.OUT, + IdGenerator.of(5L), IdGenerator.of(5L), + "2026!x", IdGenerator.of(2L)) : IdGenerator.of(1L); + if (!decoded.elementIds().contains(expectedElement)) { + throw new AssertionError("Legacy index self-read failed: " + name); + } + } + ROWS.put(name + ".type", entry.type().name()); + ROWS.put(name + ".id", hex(entry.id().asBytes())); + ROWS.put(name + ".ttl", String.valueOf(entry.ttl())); + ROWS.put(name + ".columns", String.valueOf(entry.columnsSize())); + int number = 0; + for (BackendColumn column : entry.columns()) { + ROWS.put(name + ".column." + number + ".name", hex(column.name)); + ROWS.put(name + ".column." + number + ".value", hex(column.value)); + number++; + } + } + + private static class FixtureSerializer extends BinarySerializer { + private void parseOlap(byte[] bytes, HugeVertex vertex) { + super.parseVertexOlap(bytes, vertex); + } + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { + text.append(String.format("%02x", value & 0xff)); + } + return text.toString(); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt new file mode 100644 index 0000000000..e51eca9f31 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Collections; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.query.ConditionQuery; +import org.apache.hugegraph.backend.query.IdPrefixQuery; +import org.apache.hugegraph.backend.serializer.BinarySerializer; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.HugeKeys; + +public class LegacyServerIndexQueryProbe { + public static void main(String[] args) throws Exception { + String input = "long-field-".repeat(20); + String value = ConditionQuery.concatValues(Collections.singletonList(input)); + ConditionQuery query = new ConditionQuery(HugeType.SECONDARY_INDEX); + query.eq(HugeKeys.INDEX_LABEL_ID, IdGenerator.of(15L)); + query.eq(HugeKeys.FIELD_VALUES, value); + IdPrefixQuery encoded = (IdPrefixQuery) new BinarySerializer().writeQuery(query); + String text = "server.query.field.length=" + value.length() + "\n" + + "server.query.prefix=" + hex(encoded.prefix().asBytes()) + "\n"; + Files.writeString(Path.of(args[0]).resolve("index-builder-contract.properties"), text, + StandardCharsets.UTF_8, StandardOpenOption.APPEND); + System.out.println("Original Server query: field " + value.length() + + " -> prefix " + hex(encoded.prefix().asBytes())); + } + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { text.append(String.format("%02x", value & 0xff)); } + return text.toString(); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt new file mode 100644 index 0000000000..c4a3fbdc2c --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.BaseVertex; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.structure.builder.IndexBuilder; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IndexType; + +public class LegacyStoreIndexBuilderProbe { + public static void main(String[] args) throws Exception { + HugeConfig config = new HugeConfig(Collections.emptyMap()); + PropertyKey pkey = new PropertyKey(null, IdGenerator.of(17L), "name"); + pkey.dataType(DataType.TEXT); + VertexLabel vlabel = new VertexLabel(null, IdGenerator.of(4L), "person"); + vlabel.properties(pkey.id()); + vlabel.ttl(60000L); + HugeGraphSupplier graph = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, values) -> { + switch (method.getName()) { + case "configuration": return config; + case "propertyKey": return pkey; + case "vertexLabel": + case "vertexLabelOrNone": return vlabel; + case "now": return 1609459200000L; + case "name": return "legacy-fixture"; + default: throw new AssertionError("Unexpected supplier call: " + method); + } + }); + IndexLabel ilabel = new IndexLabel(graph, IdGenerator.of(15L), "by-name"); + ilabel.indexType(IndexType.SECONDARY); + ilabel.baseType(HugeType.VERTEX_LABEL); + ilabel.baseValue(vlabel.id()); + ilabel.indexFields(pkey.id()); + String value = "long-field-".repeat(20); + BaseVertex vertex = new BaseVertex(IdGenerator.of(1L), vlabel); + vertex.addProperty(pkey, value); + vertex.expiredTime(1609459260000L); + IndexBuilder builder = new IndexBuilder(graph); + Index index = builder.buildIndex(vertex, ilabel).get(0); + BackendColumn column = new BinaryElementSerializer().writeIndex(index); + String producer = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = producer.substring(0, producer.indexOf("*/") + 2); + String text = license.replace("/*", "#").replace("*/", "#").replace(" *", "#") + "\n" + + "input.length=" + value.length() + "\n" + + "store.builder.field.length=" + index.fieldValues().toString().length() + "\n" + + "store.builder.field=" + index.fieldValues() + "\n" + + "store.builder.key=" + hex(column.name) + "\n" + + "store.builder.value=" + hex(column.value) + "\n"; + Files.writeString(Path.of(args[0]).resolve("index-builder-contract.properties"), text, + StandardCharsets.UTF_8); + System.out.println("Original Store IndexBuilder: input " + value.length() + + " -> field " + index.fieldValues()); + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { text.append(String.format("%02x", value & 0xff)); } + return text.toString(); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt new file mode 100644 index 0000000000..9a9a468c4d --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.hugegraph.HugeGraphSupplier; +import org.apache.hugegraph.backend.BackendColumn; +import org.apache.hugegraph.id.Id; +import org.apache.hugegraph.id.EdgeId; +import org.apache.hugegraph.type.define.Directions; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BinaryElementSerializer; +import org.apache.hugegraph.struct.schema.IndexLabel; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.struct.schema.VertexLabel; +import org.apache.hugegraph.structure.Index; +import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.DataType; +import org.apache.hugegraph.type.define.IndexType; + +public class LegacyStoreIndexFixtureWriter { + private static final long EXPIRY = 1609459260000L; + private static final Map INDEXES = new HashMap<>(); + private static final Map PROPERTIES = new HashMap<>(); + private static final Map OUTPUT = new LinkedHashMap<>(); + + public static void main(String[] args) throws Exception { + VertexLabel label = new VertexLabel(null, IdGenerator.of(4L), "person"); + label.ttl(60000L); + HugeGraphSupplier graph = (HugeGraphSupplier) Proxy.newProxyInstance( + HugeGraphSupplier.class.getClassLoader(), new Class[]{HugeGraphSupplier.class}, + (proxy, method, values) -> { + switch (method.getName()) { + case "vertexLabel": + case "vertexLabelOrNone": return label; + case "indexLabel": return INDEXES.get(((Id) values[0]).asLong()); + case "propertyKey": return PROPERTIES.get(((Id) values[0]).asLong()); + case "now": return 1609459200000L; + case "name": return "legacy-fixture"; + default: throw new AssertionError("Unexpected supplier call: " + method); + } + }); + PropertyKey intKey = new PropertyKey(graph, IdGenerator.of(1L), "age"); + intKey.dataType(DataType.INT); + PROPERTIES.put(1L, intKey); + PropertyKey longKey = new PropertyKey(graph, IdGenerator.of(16L), "weight"); + longKey.dataType(DataType.LONG); + PROPERTIES.put(16L, longKey); + BinaryElementSerializer serializer = new BinaryElementSerializer(); + System.out.println("Store index writer loaded from " + BinaryElementSerializer.class + .getProtectionDomain().getCodeSource().getLocation()); + user("secondary", graph, serializer, 6L, IndexType.SECONDARY, "alice"); + user("int", graph, serializer, 7L, IndexType.RANGE_INT, 7); + user("long", graph, serializer, 8L, IndexType.RANGE_LONG, 7L); + Index system = new Index(graph, IndexLabel.label(HugeType.VERTEX), true); + system.fieldValues(4L); + system.elementIds(IdGenerator.of(1L), EXPIRY); + row("system", serializer, graph, system); + Index edgeSystem = new Index(graph, IndexLabel.label(HugeType.EDGE), true); + edgeSystem.fieldValues(5L); + edgeSystem.elementIds(new EdgeId(IdGenerator.of(1L), Directions.OUT, + IdGenerator.of(5L), IdGenerator.of(5L), "2026!x", IdGenerator.of(2L)), EXPIRY); + row("system.edge", serializer, graph, edgeSystem); + String source = Files.readString(Path.of(args[1]), StandardCharsets.UTF_8); + String license = source.substring(0, source.indexOf("*/") + 2); + StringBuilder text = new StringBuilder(license.replace("/*", "#") + .replace("*/", "#").replace(" *", "#")).append('\n'); + OUTPUT.forEach((key, value) -> text.append(key).append('=').append(value).append('\n')); + Files.writeString(Path.of(args[0]).resolve("store-index-rows.properties"), text, + StandardCharsets.UTF_8); + System.out.println("Generated 5 original Store TTL index rows"); + } + + private static void user(String name, HugeGraphSupplier graph, + BinaryElementSerializer serializer, long id, + IndexType type, Object value) { + IndexLabel label = new IndexLabel(graph, IdGenerator.of(id), "index-" + id); + label.baseType(HugeType.VERTEX_LABEL); + label.baseValue(IdGenerator.of(4L)); + label.indexType(type); + label.indexFields(IdGenerator.of(type == IndexType.RANGE_LONG ? 16L : 1L)); + INDEXES.put(id, label); + Index index = new Index(graph, label, true); + index.fieldValues(value); + index.elementIds(IdGenerator.of(1L), EXPIRY); + row(name, serializer, graph, index); + } + + private static void row(String name, BinaryElementSerializer serializer, + HugeGraphSupplier graph, Index index) { + BackendColumn column = serializer.writeIndex(index); + Index decoded = serializer.parseIndex(graph, column, null); + if (decoded.expiredTime() != EXPIRY) { + throw new AssertionError("Legacy Store reader TTL mismatch: " + name); + } + OUTPUT.put(name + ".name", hex(column.name)); + OUTPUT.put(name + ".value", hex(column.value)); + OUTPUT.put(name + ".expiry", String.valueOf(EXPIRY)); + } + + private static String hex(byte[] bytes) { + StringBuilder text = new StringBuilder(); + for (byte value : bytes) { + text.append(String.format("%02x", value & 0xff)); + } + return text.toString(); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStructFixtureWriter.java.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStructFixtureWriter.java.txt new file mode 100644 index 0000000000..02d42fe869 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/LegacyStructFixtureWriter.java.txt @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.UUID; +import org.apache.hugegraph.id.IdGenerator; +import org.apache.hugegraph.serializer.BytesBuffer; +import org.apache.hugegraph.struct.schema.PropertyKey; +import org.apache.hugegraph.type.define.Cardinality; +import org.apache.hugegraph.type.define.DataType; + +public class LegacyStructFixtureWriter { + private static final StringBuilder OUTPUT = new StringBuilder(); + + public static void main(String[] args) throws Exception { + System.out.println("Writer loaded from " + BytesBuffer.class.getProtectionDomain() + .getCodeSource().getLocation()); + Path source = Path.of(args[1]); + String producer = Files.readString(source, StandardCharsets.UTF_8); + String license = producer.substring(0, producer.indexOf("*/") + 2); + OUTPUT.append(license.replace("/*", "#").replace("*/", "#") + .replace(" *", "#")).append('\n'); + scalar(DataType.BOOLEAN, true); + scalar(DataType.BYTE, (byte) -7); + scalar(DataType.INT, -123456); + scalar(DataType.LONG, Long.MIN_VALUE); + scalar(DataType.FLOAT, 1.25f); + scalar(DataType.DOUBLE, -123.125d); + scalar(DataType.DATE, new Date(1609459200123L)); + scalar(DataType.TEXT, "属性😀\u0000"); + scalar(DataType.BLOB, new byte[]{0, -1, 1, 127, -128}); + scalar(DataType.UUID, UUID.fromString("01234567-89ab-cdef-0123-456789abcdef")); + PropertyKey key = new PropertyKey(null, IdGenerator.of(101L), "legacy"); + key.dataType(DataType.INT); + key.cardinality(Cardinality.LIST); + put("list", BytesBuffer.allocate(64).writeProperty(key, Arrays.asList(7, -1, 7))); + key.cardinality(Cardinality.SET); + put("set", BytesBuffer.allocate(64).writeProperty( + key, new LinkedHashSet<>(Arrays.asList(7, -1)))); + Files.writeString(Path.of(args[0]).resolve("struct-tagged-properties.hex"), + OUTPUT, StandardCharsets.UTF_8); + System.out.println("Generated 12 tagged property fixtures"); + } + + private static void scalar(DataType type, Object value) { + put(type.name(), BytesBuffer.allocate(128).writeProperty(Cardinality.SINGLE, type, value)); + } + + private static void put(String key, BytesBuffer buffer) { + OUTPUT.append(key).append('='); + for (byte value : buffer.bytes()) { + OUTPUT.append(String.format("%02x", value & 0xff)); + } + OUTPUT.append('\n'); + } +} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/README.md b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/README.md new file mode 100644 index 0000000000..7daa6eb029 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/README.md @@ -0,0 +1,275 @@ + + +# Pre-consolidation core codec fixtures + +These fixed payloads were generated from `hugegraph/hugegraph` commit +`2f827d6e8c9c62ae858f2fc122b3a192d015e2f4`, using Java 11 and the original +`org.apache.hugegraph.backend.*` core implementations. They are not generated +by the canonical struct writer during a test run. The test checks both reading +old bytes and retaining writer byte compatibility. + +`core-codecs.hex` contains 65 named byte payloads. Comment lines carry the ASF +license; remaining entries are `key=hex`, using standard properties line +continuations for large IDs. The four `.json.txt` files contain an ASF +comment prolog and final file newline around the exact UTF-8 output from the legacy +`ConditionQuery.bytes()`. The test removes those container boundaries before decoding. +`LegacyCodecFixtureWriter.java.txt` is the producer source; its extension keeps +legacy imports outside the test compilation unit. + +## Reproduction + +Use an isolated checkout of the pinned commit, never the migration worktree: + +```sh +git clone https://github.com/hugegraph/hugegraph.git legacy-core +cd legacy-core +git checkout --detach 2f827d6e8c9c62ae858f2fc122b3a192d015e2f4 +mvn install -pl hugegraph-server/hugegraph-core -am -DskipTests +mvn dependency:build-classpath -pl hugegraph-server/hugegraph-core \ + -Dmdep.outputFile=/tmp/legacy-core-classpath.txt +``` + +Copy the producer from this fixture directory to a temporary +`LegacyCodecFixtureWriter.java` outside that checkout. Compile with +`javac -proc:none -encoding UTF-8`, using the baseline core jar plus its Maven +runtime classpath. Run `LegacyCodecFixtureWriter ` with +`java -Dfile.encoding=UTF-8 -Duser.timezone=UTC`. The output must reproduce the +fixture payloads. Keep the core jar first in the producer classpath; do not +include canonical struct classes or another HugeGraph core version. + +For the tagged property fixtures, also build the pinned `hugegraph-struct` +module with `-am` and generate its Maven runtime classpath. Compile and run +`LegacyStructFixtureWriter` with the frozen struct jar first and no core jar. +It accepts ` ` and creates +`struct-tagged-properties.hex` with 12 original tagged payloads. Both tagged +and schema-driven tests compare the common scalar suffix to independently +captured core bytes. + +The captured run used frozen baseline artifacts and logged the writer's +code source as `/tmp/hugegraph-baseline-codec-2f827d6e8/hugegraph-core-1.7.0.jar`. +The four relevant source files (`IdGenerator`, `EdgeId`, `BytesBuffer`, and +`ConditionQuery`) were byte-identical to `git show` of the pinned commit before +capture. Observed artifact SHA-256 values were: + +- core: `e53a15206fcf2f9b6ee4ba30146a1fb9814d3bf9275bdfe3f861796706fb7ce4` +- common: `564059eaa40ab70025d0a16490167cf28c615060db3f5ccbaee27f85345158d1` +- struct: `27a2cc1265a91883a5195ca315f7eaaa47ed3e880005f234603ea9cbb7567350` + +Jar hashes describe this captured build; Maven archive timestamps can change +on a fresh build. Payload reproduction, source commit, and producer source +are the durable provenance checks. + +## Coverage and limits + +Covered: signed varint/varlong limits and width boundaries; long, Unicode +string and UUID IDs, including string-header width changes and the 16 KiB +limit; incoming/outgoing edge IDs with parent and sublabel; +all scalar property data types including the original shaded Kryo fallback; +schema-driven SINGLE/LIST/SET properties; string and 4/8-byte range index IDs; +vertex query labels, numeric ranges, typed IN lists, date values, OR conditions, +limit/offset; edge query ownership, direction and page tokens; executable +COUNT(*)/AVG(age) strategies and their JSON aggregate shape; and original +Store tagged scalar/LIST/SET metadata recovery. + +The range-index fixture input is an explicit type/label/value byte layout, +not the output of a full index builder. Scalar/query fixtures alone do not prove complete storage rows. The added +row fixtures below cover specific complete layouts; they do not prove +RocksDB/HStore transactions or query-runtime compatibility. Those require integration and storage fixtures. +The old JSON date representation has no time zone; capture and date assertions +use UTC without changing that protocol. + +Core schema-driven properties are untagged; Store/struct properties use a +cardinality/type tag. They are separate wire entry points into the shared +scalar codec. This suite verifies both formats against their respective old writers and +does not interpret legacy core bytes as Store's tagged property format. + +Kryo OBJECT fixture uses a mutable `ArrayList`. The original baseline writer +can encode `Arrays.asList`, but its own reader fails to instantiate +`java.util.Arrays$ArrayList`; this existing unsupported case is not a promise +of compatibility created by the migration. The baseline UNKNOWN String and +mutable ArrayList fixtures were also independently read by the frozen core +reader before accepting them. + +## Complete BinarySerializer row fixtures + +`core-rows.properties` stores 15 complete rows emitted by the original +`BinarySerializer` from the same frozen core jar. Names, values and row IDs +are hex; `type`, `ttl` and `columns` record the real BackendEntry metadata. +These are not manually assembled from scalar fixtures. + +`LegacyRowFixtureWriter.java.txt` records the exact producer and schema. +A dynamic proxy supplies only schema lookup and a fixed clock; it throws on +unexpected graph calls. The real baseline HugeVertex/HugeEdge/HugeIndex, +BinarySerializer, and property implementations build each row. The producer +also validates every row using the original baseline reader. For OLAP it +exposes the protected original `parseVertexOlap` via a reader-only subclass; +it does not override any encoding methods. + +Schema and expected values: + +| Schema | Definition | +|---|---| +| Property 1 | `age`, INT SINGLE, value 7 | +| Property 2 | `scores`, INT LIST, value `[7, -1, 7]` | +| Property 3 | `groups`, INT SET, values `{-1, 7}` | +| Property 9 | `rank`, INT SINGLE OLAP_COMMON, value 42 | +| Property 16 | `weight`, LONG SINGLE, range-long index field | +| Property 17 | `name`, TEXT SINGLE, secondary index field | +| Vertex label 4 | `person`, TTL 60000, properties 1/2/3 | +| Vertex label 10 | `timeless`, no TTL, properties 1/2/3 | +| Edge label 5 | `knows`, TTL 60000, link 4→4, properties 1/2/3 | +| Edge label 11 | `untimed`, no TTL, link 4→4, properties 1/2/3 | +| Index labels 6/7/8 | secondary/range-int/range-long, base label 4 | +| Index labels 12/13/14 | secondary/range-int/range-long, base label 10 | +| Index label 15 | secondary, base label 4, hashed long string key | + +Timed rows expire at `1609459260000`, with the producer clock fixed at +`1609459200000`. The vertex ID is 1 (untimed vertex 3). Outgoing/incoming +edges connect 1 and 2, with sort value `2026!x` (untimed edge has an empty +sort value). Index field values are `alice`, integer 7, long 7, or +`"long-field-".repeat(20)` for the hashed row. `index.system` uses the +original system vertex-label index with field value 4 and no persisted TTL. +`index.system.edge` similarly uses field value 5 and the full edge ID. Both +original Core writers receive a positive expiry yet persist no expiry suffix +or value. The old Store writer persists the same key plus the 13-byte value +envelope for both label index kinds. + +The writer uses default BinarySerializer flags: key and index ID prefixes +enabled, partition prefix disabled. The OLAP column name is the single +vertex ID, and its value is the property ID followed by the untagged scalar. +The shared merged-row test supplies the existing vertex, matching the legacy +reader's first main row plus subsequent OLAP columns convention. + +Compile the row producer against the isolated baseline core runtime classpath +and invoke `LegacyRowFixtureWriter `. +Use Java 11, UTF-8 and UTC as above. The captured full-row file SHA-256 is +`d90cfe0b349edb832bf7425b6b8e2ddb06b3eff3f29e834cf8363b0d2fb84662`. +The exact same licensed fixture and producer are provided to Store's test +resources so ingress tests consume the original bytes directly. + +These complete row checks cover schema-driven property-group framing, TTL, +OLAP merging, ordinary/range/hashed/system indexes and their direct TTL +readers. They still do not prove every partition layout, storage transaction, +or RocksDB/HStore runtime path. + +`property.OBJECT_UNSUPPORTED_COLLECTION` retains those original bytes only +for the skip-path test. Skipping must preserve the trailing marker and TTL +without invoking Kryo instantiation. It is not used as a readable property +compatibility assertion. + +## Original Store index TTL rows + +`store-index-rows.properties` comes from the frozen baseline struct jar's +original `BinaryElementSerializer.writeIndex`, using +`LegacyStoreIndexFixtureWriter.java.txt`. The producer also decodes each row +with that same original implementation and verifies expiration time. +It emits secondary/range-int/range-long user indexes and the system +vertex-label and edge-label indexes, each with expiration `1609459260000`. +The index schemas and IDs match the complete core-row fixtures above. + +This original Store format places no expiration suffix in the key. Its +value is the exact 13-byte envelope `0x00 + Base64(big-endian long)`. +The shared schema reader must continue reading these old rows while the +new schema writer retains the pinned Server key/hash/TTL layout. The +still-supported tagged writer is separately checked against the original +Store bytes. The original system index persists TTL in this value envelope; +the original core system-index fixture does not persist TTL. + +Compile and run this producer with the frozen struct jar first, no core jar, +and the module's runtime dependencies; invoke +`LegacyStoreIndexFixtureWriter `. +The captured fixture SHA-256 is +`e9e9c967884d0d91b6cf6d5eabf2050a9bad0fe7898d1c47b58535ebdf1b9431`. + +The query date fixture preserves the legacy wall-time contract. A frozen +baseline reader probe produced epoch `1609459200123` in UTC and +`1609430400123` in Asia/Singapore from the same JSON date string +`2021-01-01 00:00:00.123`. The test computes expected local wall time without +changing the JVM default time zone after adapters have initialized. + +## Relocated Kryo OBJECT descriptors + +`core-kryo-objects.properties` captures 36 original core OBJECT payloads +without replacing any names or bytes. Each includes an explicit +`baseline_readable` receipt from the frozen original default reader. +`LegacyKryoFixtureWriter.java.txt` regenerates payloads and receipts using +the frozen core jar with its original shaded Kryo dependency. + +Twenty-four payloads were readable before migration: relocated query and ID +enums, Userdata with string/int/date entries, Class literals, an actual +BackendColumn with byte-array fields, its populated array, moved-type +null-element arrays and matrices, and nested mutable maps/lists containing +these values. Tests verify canonical runtime types and values from the exact +old bytes, plus semantic new-writer roundtrips. New writes may emit canonical +class names; they are not required to preserve deprecated Java API names. + +Twelve payloads could be written but the original default reader rejected +missing no-arg constructors: LongId/StringId/UuidId/EdgeId/BinaryId/Shard, +four schema instances, IdWithExpiredTime, and Arrays$ArrayList. Receipts retain those original +errors. These cases do not justify changing the general instantiation policy +or claiming that previously unreadable model instances were readable. +Tests instead verify that exact legacy class resolution reaches the same +constructor policy, without a ClassNotFound regression. Empty/null-element +arrays and Class literals of these types were genuinely readable and must +remain supported. + +The fixture SHA-256 is +`45c10201a1f88b38771fd5bd4e609f461729ac1d5e8fb94304fa176bfd5cf369`. + +## Existing IndexBuilder/query mismatch + +`index-builder-contract.properties` records two actual pinned execution +paths. Run `LegacyStoreIndexBuilderProbe` against the original struct jar +first; then run `LegacyServerIndexQueryProbe` against the original core jar +in a separate process. The second appends the Server prefix to the same +licensed resource. The Store probe requires the pinned IndexBuilder's +analyzer dependencies even though this example builds a secondary index. + +For TEXT property 17, index label 15, base vertex label 4, and +`"long-field-".repeat(20)`, Store's real `buildIndex` truncates the 220-character +value to `long-field-long-fiel` (20 characters). Its emitted key starts with +that shortened literal. Server's real `BinarySerializer.writeQuery`, using +`ConditionQuery.concatValues` over the full value, emits the hashed prefix +`53493a463a323234303534613200`. The old Store key does not match it. +This is an existing builder/query contract defect, not a fixture assembled +from separate guessed helper outputs. New writer/query alignment tests use +the captured original Server prefix, while retaining old Store row decoding. + +The fixture SHA-256 is +`3be36ba02c4afd58aab383549b041368fab4b9e8e32474122457b5608970161b`. + +Schema nested-class fixtures include the exact original TaskWithSchema and +all five P class literals, all four Builder interface literals, and typed +null-element arrays. Index +fixtures include original HugeIndex/IdWithExpiredTime class literals and +arrays. Actual IdWithExpiredTime decoding fails in the original default +reader and remains a recorded unsupported case. A live-graph HugeIndex +OBJECT instance is not claimed readable by this suite. + +Descriptor lookup tests independently cover the JVM 255-dimension boundary +and reject 256/5000 dimensions before allocation; unknown and primitive +array descriptors remain delegated to the normal resolver. These checks +allocate no populated multidimensional arrays. + +The label TTL regression tests exercise actual Core `readIndex`, recovered +expiration, `expiredElementIds`, clone/reset and deletion encoding, then Core +append and re-read. Both deletion and append retain the exact original Store +key; Core's primitive encoder still emits the original empty value. The +shared storage writer retains the old envelope on that same key, keeping +label expiry available without introducing an expiry suffix or duplicate +candidate key. diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-avg-query.json.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-avg-query.json.txt new file mode 100644 index 0000000000..78757f8fdc --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-avg-query.json.txt @@ -0,0 +1,17 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +{"conditions":[{"cls":"S","el":{"key":"LABEL","relation":"EQ","value":{"id":3,"cls":"org.apache.hugegraph.backend.id.IdGenerator$LongId"}}}],"optimizedType":"NONE","ids":[],"mustSortByInput":true,"resultType":"VERTEX","offset":0,"actualOffset":0,"actualStoreOffset":0,"limit":9223372036854775807,"skipDegree":9223372036854775807,"capacity":800000,"showHidden":false,"showDeleting":false,"showExpired":false,"olap":false,"withProperties":true,"orderType":"ORDER_STRICT","olapPks":[],"aggregate":{"func":"AVG","column":"age"}} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-codecs.hex b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-codecs.hex new file mode 100644 index 0000000000..9665439e6e --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-codecs.hex @@ -0,0 +1,420 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +id.long.-9223372036854775808=708000000000000000 +vlong.-9223372036854775808=81808080808080808000 +id.long.-16385=17bfff +vlong.-16385=81fffffffffffffeff7f +id.long.-16384=17c000 +vlong.-16384=81ffffffffffffff8000 +id.long.-129=077f +vlong.-129=81fffffffffffffffe7f +id.long.-128=0780 +vlong.-128=81ffffffffffffffff00 +id.long.-1=07ff +vlong.-1=81ffffffffffffffff7f +id.long.0=0800 +vlong.0=00 +id.long.1=0801 +vlong.1=01 +id.long.127=087f +vlong.127=7f +id.long.128=0880 +vlong.128=8100 +id.long.16383=183fff +vlong.16383=ff7f +id.long.16384=184000 +vlong.16384=818000 +id.long.9223372036854775807=787fffffffffffffff +vlong.9223372036854775807=ffffffffffffffff7f +vint.-2147483648=8880808000 +vint.-129=8ffffffe7f +vint.-1=8fffffff7f +vint.0=00 +vint.127=7f +vint.128=8100 +vint.16383=ff7f +vint.16384=818000 +vint.2147483647=87ffffff7f +id.text=84616c696365 +id.unicode=89e9a1b6e782b9f09f9880 +id.text.length.1=8078 +id.text.length.64=bf78787878787878787878787878787878787878787878787878787878787878787878787878787878\ +787878787878787878787878787878787878787878787878 +id.text.length.65=c040787878787878787878787878787878787878787878787878787878787878787878787878787878\ +7878787878787878787878787878787878787878787878787878 +id.text.length.256=c0ff78787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +87878787878787878787878787878787878 +id.text.length.257=c10078787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878 +id.text.length.16384=ffff787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +8787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787\ +878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878 +id.uuid=7f0123456789abcdef0123456789abcdef +edge.out=84616c6963658208030804323032362178000863 +edge.in=08638c080308043230323621780084616c696365 +property.BOOLEAN=01 +property.BYTE=8fffffff79 +property.INT=8ffff8bb40 +property.LONG=81808080808080808000 +property.FLOAT=3fa00000 +property.DOUBLE=c05ec80000000000 +property.DATE=aeebd9f9e07b +property.TEXT=0be5b19ee680a7f09f988000 +property.BLOB=0500ff017f80 +property.UUID=0123456789abcdef0123456789abcdef +property.OBJECT=2301006a6176612e7574696c2e41727261794c6973f4010303016c65676163f9020e0501 +property.UNKNOWN=0f03016c65676163792d6f626a6563f4 +property.OBJECT_UNSUPPORTED_COLLECTION=2a01006a6176612e7574696c2e4172726179732441727261794c6973f4010\ +303016c65676163f9020e0501 +schema.single=07 +schema.list=03078fffffff7f07 +schema.set=02078fffffff7f +index.string=6c6162656c21616c69636500 +index.int=a00000000380000007 +index.long=a2000000038000000000000007 diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-count-query.json.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-count-query.json.txt new file mode 100644 index 0000000000..68cf5a6f85 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-count-query.json.txt @@ -0,0 +1,17 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +{"conditions":[],"optimizedType":"NONE","ids":[],"mustSortByInput":true,"resultType":"VERTEX","offset":0,"actualOffset":0,"actualStoreOffset":0,"limit":9223372036854775807,"skipDegree":9223372036854775807,"capacity":800000,"showHidden":false,"showDeleting":false,"showExpired":false,"olap":false,"withProperties":true,"orderType":"ORDER_STRICT","olapPks":[],"aggregate":{"func":"COUNT"}} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-edge-query.json.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-edge-query.json.txt new file mode 100644 index 0000000000..fed3f9cfa3 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-edge-query.json.txt @@ -0,0 +1,17 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +{"conditions":[{"cls":"S","el":{"key":"OWNER_VERTEX","relation":"EQ","value":{"id":"alice","cls":"org.apache.hugegraph.backend.id.IdGenerator$StringId"}}},{"cls":"S","el":{"key":"DIRECTION","relation":"EQ","value":"OUT"}},{"cls":"S","el":{"key":"LABEL","relation":"EQ","value":{"id":3,"cls":"org.apache.hugegraph.backend.id.IdGenerator$LongId"}}}],"optimizedType":"NONE","ids":[],"mustSortByInput":true,"resultType":"EDGE","offset":0,"actualOffset":0,"actualStoreOffset":0,"limit":5,"skipDegree":9223372036854775807,"page":"AQIDBA\u003d\u003d","capacity":800000,"showHidden":false,"showDeleting":false,"showExpired":false,"olap":false,"withProperties":true,"orderType":"ORDER_STRICT","olapPks":[]} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-kryo-objects.properties b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-kryo-objects.properties new file mode 100644 index 0000000000..0f644d2219 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-kryo-objects.properties @@ -0,0 +1,247 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +long_id.hex=3701006f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e65726174\ +6f72244c6f6e6749e401010e +long_id.baseline_readable=false +long_id.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (miss\ +ing no-arg constructor): org.apache.hugegraph.backend.id.IdGenerator$LongId +string_id.hex=4201006f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261\ +746f7224537472696e6749e40100016c65676163792d69e4 +string_id.baseline_readable=false +string_id.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (mi\ +ssing no-arg constructor): org.apache.hugegraph.backend.id.IdGenerator$StringId +uuid_id.hex=4601006f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e65726174\ +6f72245575696449e401010123456789abcdef0123456789abcdef +uuid_id.baseline_readable=false +uuid_id.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (miss\ +ing no-arg constructor): org.apache.hugegraph.backend.id.IdGenerator$UuidId +edge_id.hex=813501006f72672e6170616368652e6875676567726170682e6261636b656e642e69642e4564676549e40100\ +00010201016f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746f72244c\ +6f6e6749e401010601026f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261\ +746f7224537472696e6749e40100016c65676163792d69e4010101010e01736f72f40101010108 +edge_id.baseline_readable=false +edge_id.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (miss\ +ing no-arg constructor): org.apache.hugegraph.backend.id.EdgeId +binary_id.hex=81040100c4016f72672e6170616368652e6875676567726170682e6261636b656e642e73657269616c697a\ +65722e42696e6172794261636b656e64456e7472792442696e617279496401010401020301016f72672e6170616368652e68\ +75676567726170682e6261636b656e642e69642e496447656e657261746f72244c6f6e6749e401010e +binary_id.baseline_readable=false +binary_id.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (mi\ +ssing no-arg constructor): org.apache.hugegraph.backend.serializer.BinaryBackendEntry$BinaryId +shard.hex=3601006f72672e6170616368652e6875676567726170682e6261636b656e642e73746f72652e53686172e40101\ +656ee4180173746172f4 +shard.baseline_readable=false +shard.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (missin\ +g no-arg constructor): org.apache.hugegraph.backend.store.Shard +property_key.hex=811801006f72672e6170616368652e6875676567726170682e736368656d612e50726f70657274794b6\ +5f9010101010101090001016f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657\ +261746f72244c6f6e6749e4010116016167e5010101026f72672e6170616368652e6875676567726170682e736368656d612\ +e55736572646174e101000101 +property_key.baseline_readable=false +property_key.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created \ +(missing no-arg constructor): org.apache.hugegraph.schema.PropertyKey +vertex_label.hex=815001006f72672e6170616368652e6875676567726170682e736368656d612e5665727465784c61626\ +5ec01010001016f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746f722\ +44c6f6e6749e4010118010101026a6176612e7574696c2e486173685365f4010001706572736fee0102010001036a6176612\ +e7574696c2e41727261794c6973f4010001020100010100010101010001046f72672e6170616368652e68756765677261706\ +82e736368656d612e55736572646174e10100 +vertex_label.baseline_readable=false +vertex_label.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created \ +(missing no-arg constructor): org.apache.hugegraph.schema.VertexLabel +edge_label.hex=815a01006f72672e6170616368652e6875676567726170682e736368656d612e456467654c616265ec010\ +101010001010001016f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746\ +f72244c6f6e6749e401011a01026a6176612e7574696c2e486173685365f4010001020100016b6e6f77f3010201000102010\ +001036a6176612e7574696c2e41727261794c6973f401000101010100010101010c0001010c01046f72672e6170616368652\ +e6875676567726170682e736368656d612e55736572646174e10100 +edge_label.baseline_readable=false +edge_label.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (m\ +issing no-arg constructor): org.apache.hugegraph.schema.EdgeLabel +index_label.hex=813201006f72672e6170616368652e6875676567726170682e736368656d612e496e6465784c616265ec\ +01012001016f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746f72244c\ +6f6e6749e401010000010101011c01026a6176612e7574696c2e41727261794c6973f4010001010162792d6167e501010103\ +6f72672e6170616368652e6875676567726170682e736368656d612e55736572646174e10100 +index_label.baseline_readable=false +index_label.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (\ +missing no-arg constructor): org.apache.hugegraph.schema.IndexLabel +aggregate_func.hex=3e01006f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e41676\ +77265676174652441676772656761746546756ee30104 +aggregate_func.baseline_readable=true +aggregate_func.baseline_type=org.apache.hugegraph.backend.query.Aggregate$AggregateFunc +relation_type.hex=3d01006f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e436f6e\ +646974696f6e2452656c6174696f6e547970e50103 +relation_type.baseline_readable=true +relation_type.baseline_type=org.apache.hugegraph.backend.query.Condition$RelationType +condition_type.hex=3e01006f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e436f6\ +e646974696f6e24436f6e646974696f6e547970e50104 +condition_type.baseline_readable=true +condition_type.baseline_type=org.apache.hugegraph.backend.query.Condition$ConditionType +query_order.hex=3201006f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e51756572\ +79244f726465f20102 +query_order.baseline_readable=true +query_order.baseline_type=org.apache.hugegraph.backend.query.Query$Order +query_order_type.hex=3601006f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e517\ +5657279244f72646572547970e50103 +query_order_type.baseline_readable=true +query_order_type.baseline_type=org.apache.hugegraph.backend.query.Query$OrderType +optimized_type.hex=4301006f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e436f6\ +e646974696f6e5175657279244f7074696d697a6564547970e50105 +optimized_type.baseline_readable=true +optimized_type.baseline_type=org.apache.hugegraph.backend.query.ConditionQuery$OptimizedType +id_type.hex=2d01006f72672e6170616368652e6875676567726170682e6261636b656e642e69642e4964244964547970e5\ +0103 +id_type.baseline_readable=true +id_type.baseline_type=org.apache.hugegraph.backend.id.Id$IdType +graph_type_class.hex=3d01006a6176612e6c616e672e436c6173f30101016f72672e6170616368652e687567656772617\ +0682e7374727563747572652e4772617068547970e500 +graph_type_class.baseline_readable=true +graph_type_class.baseline_type=java.lang.Class +id_array.hex=2a01005b4c6f72672e6170616368652e6875676567726170682e6261636b656e642e69642e4964bb010200 +id_array.baseline_readable=true +id_array.baseline_type=[Lorg.apache.hugegraph.backend.id.Id; +id_matrix.hex=2f01005b5b4c6f72672e6170616368652e6875676567726170682e6261636b656e642e69642e4964bb0103\ +0102000101 +id_matrix.baseline_readable=true +id_matrix.baseline_type=[[Lorg.apache.hugegraph.backend.id.Id; +shard_array.hex=3001005b4c6f72672e6170616368652e6875676567726170682e6261636b656e642e73746f72652e5368\ +617264bb010200 +shard_array.baseline_readable=true +shard_array.baseline_type=[Lorg.apache.hugegraph.backend.store.Shard; +schema_array.hex=2f01005b4c6f72672e6170616368652e6875676567726170682e736368656d612e50726f70657274794\ +b6579bb010200 +schema_array.baseline_readable=true +schema_array.baseline_type=[Lorg.apache.hugegraph.schema.PropertyKey; +userdata.hex=6301006f72672e6170616368652e6875676567726170682e736368656d612e55736572646174e1010303017\ +e6372656174655f74696de501016a6176612e7574696c2e446174e501fbe0f9d9eb2e0301636f756ef4020e03017461e7030\ +16c65676163f9 +userdata.baseline_readable=true +userdata.baseline_type=org.apache.hugegraph.schema.Userdata +backend_column.hex=4801006f72672e6170616368652e6875676567726170682e6261636b656e642e73746f72652e42616\ +36b656e64456e747279244261636b656e64436f6c756dee010103010201030304 +backend_column.baseline_readable=true +backend_column.baseline_type=org.apache.hugegraph.backend.store.BackendEntry$BackendColumn +backend_column_array.hex=810f0100c1015b4c6f72672e6170616368652e6875676567726170682e6261636b656e642e7\ +3746f72652e4261636b656e64456e747279244261636b656e64436f6c756d6e3b010301016f72672e6170616368652e68756\ +76567726170682e6261636b656e642e73746f72652e4261636b656e64456e747279244261636b656e64436f6c756dee01010\ +301020103030400 +backend_column_array.baseline_readable=true +backend_column_array.baseline_type=[Lorg.apache.hugegraph.backend.store.BackendEntry$BackendColumn; +backend_column_class.hex=5201006a6176612e6c616e672e436c6173f30101016f72672e6170616368652e68756765677\ +26170682e6261636b656e642e73746f72652e4261636b656e64456e747279244261636b656e64436f6c756dee00 +backend_column_class.baseline_readable=true +backend_column_class.baseline_type=java.lang.Class +class_list.hex=842601006a6176612e7574696c2e41727261794c6973f4010a01016a6176612e6c616e672e436c6173f30\ +101026f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746f72244c6f6e6\ +749e40001010101036f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746\ +f7224537472696e6749e40001010101046f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496\ +447656e657261746f72245575696449e40001010101056f72672e6170616368652e6875676567726170682e6261636b656e6\ +42e69642e4564676549e4000101010106c4016f72672e6170616368652e6875676567726170682e6261636b656e642e73657\ +269616c697a65722e42696e6172794261636b656e64456e7472792442696e61727949640001010101076f72672e617061636\ +8652e6875676567726170682e6261636b656e642e73746f72652e53686172e40001010101086f72672e6170616368652e687\ +5676567726170682e736368656d612e50726f70657274794b65f90001010101096f72672e6170616368652e6875676567726\ +170682e736368656d612e5665727465784c616265ec00010101010a6f72672e6170616368652e6875676567726170682e736\ +368656d612e456467654c616265ec00010101010b6f72672e6170616368652e6875676567726170682e736368656d612e496\ +e6465784c616265ec00 +class_list.baseline_readable=true +class_list.baseline_type=java.util.ArrayList +contract_classes.hex=843801006a6176612e7574696c2e41727261794c6973f4010a01016a6176612e6c616e672e436c6\ +173f30101026f72672e6170616368652e6875676567726170682e747970652e4e616d6561626ce50001010101036f72672e6\ +170616368652e6875676567726170682e747970652e5479706561626ce50001010101046f72672e6170616368652e6875676\ +567726170682e747970652e496e64657861626ce50001010101056f72672e6170616368652e6875676567726170682e74797\ +0652e50726f706572746961626ce50001010101066f72672e6170616368652e6875676567726170682e6261636b656e642e6\ +9642e4964557469ec0001010101076f72672e6170616368652e6875676567726170682e6261636b656e642e69642e53706c6\ +963696e67496447656e657261746ff20001010101086f72672e6170616368652e6875676567726170682e736368656d612e6\ +275696c6465722e536368656d614275696c6465f2000101010109c8016f72672e6170616368652e6875676567726170682e6\ +261636b656e642e71756572792e73657269616c697a65722e416273747261637453657269616c697a6572416461707465720\ +0010101010a6f72672e6170616368652e6875676567726170682e6261636b656e642e71756572792e73657269616c697a657\ +22e5175657279416461707465f200010101010b6f72672e6170616368652e6875676567726170682e6261636b656e642e717\ +56572792e73657269616c697a65722e51756572794964416461707465f200 +contract_classes.baseline_readable=true +contract_classes.baseline_type=java.util.ArrayList +schema_nested_classes.hex=841f01006a6176612e7574696c2e41727261794c6973f4010a01016a6176612e6c616e672e\ +436c6173f30101026f72672e6170616368652e6875676567726170682e736368656d612e536368656d61456c656d656e7424\ +5461736b57697468536368656de10001010101036f72672e6170616368652e6875676567726170682e736368656d612e5072\ +6f70657274794b657924d00001010101046f72672e6170616368652e6875676567726170682e736368656d612e5665727465\ +784c6162656c24d00001010101056f72672e6170616368652e6875676567726170682e736368656d612e456467654c616265\ +6c24d00001010101066f72672e6170616368652e6875676567726170682e736368656d612e496e6465784c6162656c24d000\ +01010101076f72672e6170616368652e6875676567726170682e736368656d612e536368656d61456c656d656e7424d00001\ +010101086f72672e6170616368652e6875676567726170682e736368656d612e50726f70657274794b6579244275696c6465\ +f20001010101096f72672e6170616368652e6875676567726170682e736368656d612e5665727465784c6162656c24427569\ +6c6465f200010101010a6f72672e6170616368652e6875676567726170682e736368656d612e456467654c6162656c244275\ +696c6465f200010101010b6f72672e6170616368652e6875676567726170682e736368656d612e496e6465784c6162656c24\ +4275696c6465f200 +schema_nested_classes.baseline_readable=true +schema_nested_classes.baseline_type=java.util.ArrayList +schema_nested_arrays.hex=842401006a6176612e7574696c2e41727261794c6973f4010a01015b4c6f72672e617061636\ +8652e6875676567726170682e736368656d612e536368656d61456c656d656e74245461736b57697468536368656d61bb010\ +20001025b4c6f72672e6170616368652e6875676567726170682e736368656d612e50726f70657274794b65792450bb01020\ +001035b4c6f72672e6170616368652e6875676567726170682e736368656d612e5665727465784c6162656c2450bb0102000\ +1045b4c6f72672e6170616368652e6875676567726170682e736368656d612e456467654c6162656c2450bb01020001055b4\ +c6f72672e6170616368652e6875676567726170682e736368656d612e496e6465784c6162656c2450bb01020001065b4c6f7\ +2672e6170616368652e6875676567726170682e736368656d612e536368656d61456c656d656e742450bb01020001075b4c6\ +f72672e6170616368652e6875676567726170682e736368656d612e50726f70657274794b6579244275696c646572bb01020\ +001085b4c6f72672e6170616368652e6875676567726170682e736368656d612e5665727465784c6162656c244275696c646\ +572bb01020001095b4c6f72672e6170616368652e6875676567726170682e736368656d612e456467654c6162656c2442756\ +96c646572bb010200010a5b4c6f72672e6170616368652e6875676567726170682e736368656d612e496e6465784c6162656\ +c244275696c646572bb010200 +schema_nested_arrays.baseline_readable=true +schema_nested_arrays.baseline_type=java.util.ArrayList +index_classes.hex=811401006a6176612e7574696c2e41727261794c6973f4010201016a6176612e6c616e672e436c6173\ +f30101026f72672e6170616368652e6875676567726170682e7374727563747572652e48756765496e6465f8000101010103\ +6f72672e6170616368652e6875676567726170682e7374727563747572652e48756765496e64657824496457697468457870\ +6972656454696de500 +index_classes.baseline_readable=true +index_classes.baseline_type=java.util.ArrayList +index_array.hex=3001005b4c6f72672e6170616368652e6875676567726170682e7374727563747572652e48756765496e\ +646578bb010200 +index_array.baseline_readable=true +index_array.baseline_type=[Lorg.apache.hugegraph.structure.HugeIndex; +expiry_id_array.hex=4201005b4c6f72672e6170616368652e6875676567726170682e7374727563747572652e48756765\ +496e646578244964576974684578706972656454696d65bb010200 +expiry_id_array.baseline_readable=true +expiry_id_array.baseline_type=[Lorg.apache.hugegraph.structure.HugeIndex$IdWithExpiredTime; +expiry_id.hex=7a01006f72672e6170616368652e6875676567726170682e7374727563747572652e48756765496e646578\ +244964576974684578706972656454696de501c0e9fab3d75d01016f72672e6170616368652e6875676567726170682e6261\ +636b656e642e69642e496447656e657261746f72244c6f6e6749e401010e +expiry_id.baseline_readable=false +expiry_id.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot be created (mi\ +ssing no-arg constructor): org.apache.hugegraph.structure.HugeIndex$IdWithExpiredTime +nested.hex=870301006a6176612e7574696c2e4c696e6b6564486173684d61f001050301636c61737365f301016a6176612\ +e7574696c2e41727261794c6973f4010a01026a6176612e6c616e672e436c6173f30101036f72672e6170616368652e68756\ +76567726170682e6261636b656e642e69642e496447656e657261746f72244c6f6e6749e40001020101046f72672e6170616\ +368652e6875676567726170682e6261636b656e642e69642e496447656e657261746f7224537472696e6749e400010201010\ +56f72672e6170616368652e6875676567726170682e6261636b656e642e69642e496447656e657261746f72245575696449e\ +40001020101066f72672e6170616368652e6875676567726170682e6261636b656e642e69642e4564676549e400010201010\ +7c4016f72672e6170616368652e6875676567726170682e6261636b656e642e73657269616c697a65722e42696e617279426\ +1636b656e64456e7472792442696e61727949640001020101086f72672e6170616368652e6875676567726170682e6261636\ +b656e642e73746f72652e53686172e40001020101096f72672e6170616368652e6875676567726170682e736368656d612e5\ +0726f70657274794b65f900010201010a6f72672e6170616368652e6875676567726170682e736368656d612e56657274657\ +84c616265ec00010201010b6f72672e6170616368652e6875676567726170682e736368656d612e456467654c616265ec000\ +10201010c6f72672e6170616368652e6875676567726170682e736368656d612e496e6465784c616265ec0003016d6574616\ +46174e1010d6f72672e6170616368652e6875676567726170682e736368656d612e55736572646174e1010303017e6372656\ +174655f74696de5010e6a6176612e7574696c2e446174e501fbe0f9d9eb2e0301636f756ef4020e03017461e703016c65676\ +163f903016964f3010f5b5b4c6f72672e6170616368652e6875676567726170682e6261636b656e642e69642e4964bb01030\ +10200010103017072656469636174e501106f72672e6170616368652e6875676567726170682e6261636b656e642e7175657\ +2792e436f6e646974696f6e2452656c6174696f6e547970e501030301636f6c756dee01116f72672e6170616368652e68756\ +76567726170682e6261636b656e642e73746f72652e4261636b656e64456e747279244261636b656e64436f6c756dee01010\ +3010201030304 +nested.baseline_readable=true +nested.baseline_type=java.util.LinkedHashMap +unsupported_arrays_list.hex=2a01006a6176612e7574696c2e4172726179732441727261794c6973f4010303016c6567\ +6163f9020e0501 +unsupported_arrays_list.baseline_readable=false +unsupported_arrays_list.baseline_error=org.apache.tinkerpop.shaded.kryo.KryoException: Class cannot \ +be created (missing no-arg constructor): java.util.Arrays$ArrayList diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-query.json.txt b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-query.json.txt new file mode 100644 index 0000000000..8d86059b09 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-query.json.txt @@ -0,0 +1,17 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +{"conditions":[{"cls":"S","el":{"key":"LABEL","relation":"EQ","value":{"id":3,"cls":"org.apache.hugegraph.backend.id.IdGenerator$LongId"}}},{"cls":"U","el":{"key":{"cls":"L","el":{"id":11}},"relation":"GTE","value":18,"valuecls":"java.lang.Integer"}},{"cls":"U","el":{"key":{"cls":"L","el":{"id":12}},"relation":"IN","value":[20,30],"valuecls":"java.lang.Long"}},{"cls":"U","el":{"key":{"cls":"L","el":{"id":13}},"relation":"EQ","value":"2021-01-01 00:00:00.123","valuecls":"java.util.Date"}},{"cls":"O","el":{"left":{"cls":"U","el":{"key":{"cls":"L","el":{"id":14}},"relation":"EQ","value":"alice"}},"right":{"cls":"U","el":{"key":{"cls":"L","el":{"id":14}},"relation":"EQ","value":"bob"}}}}],"optimizedType":"NONE","ids":[],"mustSortByInput":true,"resultType":"VERTEX","offset":7,"actualOffset":0,"actualStoreOffset":0,"limit":19,"skipDegree":9223372036854775807,"capacity":800000,"showHidden":false,"showDeleting":false,"showExpired":false,"olap":false,"withProperties":true,"orderType":"ORDER_STRICT","olapPks":[]} diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-rows.properties b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-rows.properties new file mode 100644 index 0000000000..fd489e58c1 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/core-rows.properties @@ -0,0 +1,108 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +now=1609459200000 +expiry=1609459260000 +vertex.type=VERTEX +vertex.id=0801 +vertex.ttl=60000 +vertex.columns=1 +vertex.column.0.name=0801 +vertex.column.0.value=08040301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +edge.out.type=EDGE_OUT +edge.out.id=08018208050805323032362178000802 +edge.out.ttl=60000 +edge.out.columns=1 +edge.out.column.0.name=08018208050805323032362178000802 +edge.out.column.0.value=0301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +edge.in.type=EDGE_IN +edge.in.id=08028c08050805323032362178000801 +edge.in.ttl=60000 +edge.in.columns=1 +edge.in.column.0.name=08028c08050805323032362178000801 +edge.in.column.0.value=0301070203078fffffff7f0703028fffffff7f07aeebd9fdb460 +olap.type=OLAP +olap.id=0801 +olap.ttl=0 +olap.columns=1 +olap.column.0.name=0801 +olap.column.0.value=092a +index.secondary.type=SECONDARY_INDEX +index.secondary.id=53493a363a616c69636500 +index.secondary.ttl=60000 +index.secondary.columns=1 +index.secondary.column.0.name=53493a363a616c696365000801aeebd9fdb460 +index.secondary.column.0.value= +index.int.type=RANGE_INT_INDEX +index.int.id=a00000000780000007 +index.int.ttl=60000 +index.int.columns=1 +index.int.column.0.name=a000000007800000070801aeebd9fdb460 +index.int.column.0.value= +index.long.type=RANGE_LONG_INDEX +index.long.id=a2000000088000000000000007 +index.long.ttl=60000 +index.long.columns=1 +index.long.column.0.name=a20000000880000000000000070801aeebd9fdb460 +index.long.column.0.value= +vertex.untimed.type=VERTEX +vertex.untimed.id=0803 +vertex.untimed.ttl=0 +vertex.untimed.columns=1 +vertex.untimed.column.0.name=0803 +vertex.untimed.column.0.value=080a0301070203078fffffff7f0703028fffffff7f07 +edge.untimed.type=EDGE_OUT +edge.untimed.id=080182080b080b000802 +edge.untimed.ttl=0 +edge.untimed.columns=1 +edge.untimed.column.0.name=080182080b080b000802 +edge.untimed.column.0.value=0301070203078fffffff7f0703028fffffff7f07 +index.secondary.untimed.type=SECONDARY_INDEX +index.secondary.untimed.id=53493a433a616c69636500 +index.secondary.untimed.ttl=0 +index.secondary.untimed.columns=1 +index.secondary.untimed.column.0.name=53493a433a616c696365000801 +index.secondary.untimed.column.0.value= +index.int.untimed.type=RANGE_INT_INDEX +index.int.untimed.id=a00000000d80000007 +index.int.untimed.ttl=0 +index.int.untimed.columns=1 +index.int.untimed.column.0.name=a00000000d800000070801 +index.int.untimed.column.0.value= +index.long.untimed.type=RANGE_LONG_INDEX +index.long.untimed.id=a20000000e8000000000000007 +index.long.untimed.ttl=0 +index.long.untimed.columns=1 +index.long.untimed.column.0.name=a20000000e80000000000000070801 +index.long.untimed.column.0.value= +index.hashed.type=SECONDARY_INDEX +index.hashed.id=53493a463a323234303534613200 +index.hashed.ttl=60000 +index.hashed.columns=1 +index.hashed.column.0.name=53493a463a3232343035346132000801aeebd9fdb460 +index.hashed.column.0.value=6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d6c6f6e672d6669656c642d +index.system.type=VERTEX_LABEL_INDEX +index.system.id=56493a2d313a3400 +index.system.ttl=0 +index.system.columns=1 +index.system.column.0.name=56493a2d313a34000801 +index.system.column.0.value= +index.system.edge.type=EDGE_LABEL_INDEX +index.system.edge.id=45493a2d323a3500 +index.system.edge.ttl=0 +index.system.edge.columns=1 +index.system.edge.column.0.name=45493a2d323a35007e08018208050805323032362178000802 +index.system.edge.column.0.value= diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/index-builder-contract.properties b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/index-builder-contract.properties new file mode 100644 index 0000000000..a6139eef41 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/index-builder-contract.properties @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +input.length=220 +store.builder.field.length=20 +store.builder.field=long-field-long-fiel +store.builder.key=53493a463a6c6f6e672d6669656c642d6c6f6e672d6669656c000801 +store.builder.value=00414141426472732f576d413d +server.query.field.length=220 +server.query.prefix=53493a463a323234303534613200 diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/store-index-rows.properties b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/store-index-rows.properties new file mode 100644 index 0000000000..7f5a599ed4 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/store-index-rows.properties @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +secondary.name=53493a363a616c696365000801 +secondary.value=00414141426472732f576d413d +secondary.expiry=1609459260000 +int.name=a000000007800000070801 +int.value=00414141426472732f576d413d +int.expiry=1609459260000 +long.name=a20000000880000000000000070801 +long.value=00414141426472732f576d413d +long.expiry=1609459260000 +system.name=56493a2d313a34000801 +system.value=00414141426472732f576d413d +system.expiry=1609459260000 +system.edge.name=45493a2d323a35007e08018208050805323032362178000802 +system.edge.value=00414141426472732f576d413d +system.edge.expiry=1609459260000 diff --git a/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/struct-tagged-properties.hex b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/struct-tagged-properties.hex new file mode 100644 index 0000000000..0602e40ed4 --- /dev/null +++ b/hugegraph-struct/src/test/resources/compatibility/2f827d6e8/struct-tagged-properties.hex @@ -0,0 +1,28 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # +BOOLEAN=4201 +BYTE=438fffffff79 +INT=448ffff8bb40 +LONG=4581808080808080808000 +FLOAT=463fa00000 +DOUBLE=47c05ec80000000000 +DATE=4aaeebd9f9e07b +TEXT=480be5b19ee680a7f09f988000 +BLOB=490500ff017f80 +UUID=4b0123456789abcdef0123456789abcdef +list=8403078fffffff7f07 +set=c402078fffffff7f diff --git a/install-dist/release-docs/LICENSE b/install-dist/release-docs/LICENSE index c89ada3234..d3a1ab7168 100644 --- a/install-dist/release-docs/LICENSE +++ b/install-dist/release-docs/LICENSE @@ -277,9 +277,11 @@ the corresponding per-component license file. https://central.sonatype.com/artifact/com.carrotsearch/hppc/0.7.1 -> Apache 2.0 https://central.sonatype.com/artifact/com.chenlb.mmseg4j/mmseg4j-core/1.10.0 -> Apache 2.0 https://central.sonatype.com/artifact/com.codahale.metrics/metrics-core/3.0.2 -> Apache 2.0 + https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-annotations/2.12.6 -> Apache 2.0 https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-annotations/2.13.0 -> Apache 2.0 https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-annotations/2.14.0-rc1 -> Apache 2.0 https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-annotations/2.15.2 -> Apache 2.0 + https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-core/2.12.6 -> Apache 2.0 https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-core/2.13.0 -> Apache 2.0 https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-core/2.13.2 -> Apache 2.0 https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-core/2.14.0-rc1 -> Apache 2.0 diff --git a/install-dist/release-docs/licenses/LICENSE-spring-boot-jarmode-layertools-2.7.1.txt b/install-dist/release-docs/licenses/LICENSE-spring-boot-jarmode-layertools-2.7.1.txt new file mode 100644 index 0000000000..823c1c8e98 --- /dev/null +++ b/install-dist/release-docs/licenses/LICENSE-spring-boot-jarmode-layertools-2.7.1.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/install-dist/scripts/dependency/check_dependencies.sh b/install-dist/scripts/dependency/check_dependencies.sh index 0fadfa3132..47a7ff5ae1 100644 --- a/install-dist/scripts/dependency/check_dependencies.sh +++ b/install-dist/scripts/dependency/check_dependencies.sh @@ -16,20 +16,12 @@ # limitations under the License. # -BASE_PATH=$( - cd "$(dirname "$0")" || exit 1 - pwd -) +set -euo pipefail -# check whether there are new third-party dependencies by diff command, -# diff generated 'current-dependencies.txt' file with 'known-dependencies.txt' file. -diff -w -B -U0 <(sort <"${BASE_PATH}"/known-dependencies.txt) \ - <(sort <"${BASE_PATH}"/current-dependencies.txt) >${BASE_PATH}/result.txt +BASE_PATH=$(cd "$(dirname "$0")" && pwd) +KNOWN_FILE=${1:-$BASE_PATH/known-dependencies.txt} +CURRENT_FILE=${2:-$BASE_PATH/current-dependencies.txt} -# if has new third-party,the Action will fail and print diff -if [ -s "${BASE_PATH}"/result.txt ]; then - cat "${BASE_PATH}"/result.txt - exit 1 -else - echo 'All third dependencies is known!' -fi +# Missing/malformed inputs and scan failures must not produce a green diff. +python3 "$BASE_PATH/dependency_inventory.py" check \ + --known "$KNOWN_FILE" --current "$CURRENT_FILE" diff --git a/install-dist/scripts/dependency/dependency_inventory.py b/install-dist/scripts/dependency/dependency_inventory.py new file mode 100644 index 0000000000..f80728487a --- /dev/null +++ b/install-dist/scripts/dependency/dependency_inventory.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Inventory the union of Maven runtime dependencies and actually shipped jars. + +Keep the historical filename exclusions for project artifacts. Boot repackaging +can inject jars or include provided dependencies absent from Maven's runtime +scope, so collect flat and nested distribution libraries as well. Comparison +remains strict: removals and additions both require updating the approved list. +""" + +import argparse +import difflib +import io +import os +from pathlib import Path +import re +import sys +import tempfile +import zipfile + + +class InventoryFailure(Exception): + pass + + +def third_party(name): + # Preserve the former egrep -v '^hg|hugegraph|hubble' inventory convention. + return not re.search(r'^hg|hugegraph|hubble', name) + + +def validate_name(name): + if not re.fullmatch(r'[A-Za-z0-9_.+-]+\.jar', name): + raise InventoryFailure(f'Invalid dependency jar filename: {name}') + + +def scan_shipped_jar(source, name, origin, result): + validate_name(name) + try: + with zipfile.ZipFile(source) as archive: + if third_party(name): + result.add(name) + for entry in archive.namelist(): + if entry.startswith(('BOOT-INF/lib/', 'WEB-INF/lib/')) and entry.endswith('.jar'): + scan_shipped_jar(io.BytesIO(archive.read(entry)), Path(entry).name, + origin + '!/' + entry, result) + except (OSError, zipfile.BadZipFile, RuntimeError) as error: + raise InventoryFailure(f'Cannot inspect shipped jar {origin}: {error}') from error + + +def collect(runtime, root, revision): + if not re.fullmatch(r'[A-Za-z0-9_.+-]+', revision): + raise InventoryFailure(f'Invalid distribution revision: {revision}') + if not runtime.is_dir(): + raise InventoryFailure(f'Missing Maven runtime dependency directory: {runtime}') + files = sorted(runtime.iterdir()) + if not files: + raise InventoryFailure(f'Empty Maven runtime dependency directory: {runtime}') + result = set() + for path in files: + validate_name(path.name) + try: + # Runtime copy has already resolved each artifact; validate its jar + # without treating nested project packaging as new Maven coordinates. + with zipfile.ZipFile(path): + pass + except (OSError, zipfile.BadZipFile) as error: + raise InventoryFailure(f'Cannot inspect resolved jar {path}: {error}') from error + if third_party(path.name): + result.add(path.name) + for kind in ('server', 'pd', 'store'): + distribution = root / ('hugegraph-' + kind) / f'apache-hugegraph-{kind}-{revision}' + library = distribution / 'lib' + jars = sorted(library.rglob('*.jar')) + if not library.is_dir() or not jars: + raise InventoryFailure(f'Missing packaged {kind} dependency jars: {library}') + for directory in ('ext', 'plugins'): + jars.extend(sorted((distribution / directory).rglob('*.jar'))) + for path in jars: + scan_shipped_jar(path, path.name, str(path), result) + if not result: + raise InventoryFailure('No third-party dependencies found') + return result + + +def read_inventory(path): + values = [] + for line in path.read_text().splitlines(): + name = line.strip() + if name: + validate_name(name) + values.append(name) + if not values: + raise InventoryFailure(f'Empty dependency inventory: {path}') + if len(values) != len(set(values)): + raise InventoryFailure(f'Duplicate dependency inventory entries: {path}') + return sorted(values) + + +def compare(known, current): + approved, observed = read_inventory(known), read_inventory(current) + difference = ''.join(difflib.unified_diff([name + '\n' for name in approved], + [name + '\n' for name in observed], + fromfile=str(known), tofile=str(current), n=0)) + if difference: + print(difference, end='') + return 1 + print('All third-party dependencies match the approved runtime and shipped inventory.') + return 0 + + +def write_inventory(output, names): + output.parent.mkdir(parents=True, exist_ok=True) + temporary = None + try: + with tempfile.NamedTemporaryFile(mode='w', dir=output.parent, delete=False) as handle: + temporary = Path(handle.name) + handle.write('\n'.join(sorted(names)) + '\n') + os.replace(temporary, output) + finally: + if temporary is not None: + temporary.unlink(missing_ok=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + commands = parser.add_subparsers(dest='command', required=True) + producer = commands.add_parser('collect') + producer.add_argument('--runtime', type=Path, required=True) + producer.add_argument('--root', type=Path, required=True) + producer.add_argument('--revision', required=True) + producer.add_argument('--output', type=Path, required=True) + checker = commands.add_parser('check') + checker.add_argument('--known', type=Path, required=True) + checker.add_argument('--current', type=Path, required=True) + args = parser.parse_args() + try: + if args.command == 'check': + return compare(args.known, args.current) + names = collect(args.runtime, args.root, args.revision) + write_inventory(args.output, names) + print(f'Wrote {len(names)} runtime and shipped dependency filenames to {args.output}') + return 0 + except (InventoryFailure, OSError, UnicodeError) as error: + print(f'Dependency inventory FAILED: {error}', file=sys.stderr) + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/install-dist/scripts/dependency/regenerate_known_dependencies.sh b/install-dist/scripts/dependency/regenerate_known_dependencies.sh index 5251f0658a..8b6d54bcda 100644 --- a/install-dist/scripts/dependency/regenerate_known_dependencies.sh +++ b/install-dist/scripts/dependency/regenerate_known_dependencies.sh @@ -16,18 +16,27 @@ # limitations under the License. # -BASE_PATH=$(cd "$(dirname $0)" || exit; pwd) -DEP_PATH=$BASE_PATH/all_dependencies +set -euo pipefail + +BASE_PATH=$(cd "$(dirname "$0")" && pwd) +ROOT_PATH=$(cd "$BASE_PATH/../../.." && pwd) FILE_NAME=${1:-known-dependencies.txt} +MAVEN_COMMAND=${MAVEN_COMMAND:-mvn} -if [[ -d $DEP_PATH ]];then - echo "rm -r -f DEP_PATH" - rm -r -f $DEP_PATH +if [[ "$FILE_NAME" = /* ]]; then + OUTPUT_PATH=$FILE_NAME +else + OUTPUT_PATH=$BASE_PATH/$FILE_NAME fi -cd "$BASE_PATH"/../../../ || exit - -mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=$DEP_PATH +# Only remove this invocation's new temporary directory, never a shared folder. +DEPENDENCY_TEMP=$(mktemp -d "${TMPDIR:-/tmp}/hugegraph-dependencies.XXXXXX") +trap 'rm -rf -- "$DEPENDENCY_TEMP"' EXIT -ls $DEP_PATH | egrep -v "^hg|hugegraph|hubble" | sort -n > $BASE_PATH/$FILE_NAME -rm -r -f $DEP_PATH +cd "$ROOT_PATH" +"$MAVEN_COMMAND" -B -ntp dependency:copy-dependencies -DincludeScope=runtime \ + "-DoutputDirectory=$DEPENDENCY_TEMP/runtime" +REVISION=$("$MAVEN_COMMAND" -q -DforceStdout help:evaluate -Dexpression=project.version) +python3 "$BASE_PATH/dependency_inventory.py" collect \ + --runtime "$DEPENDENCY_TEMP/runtime" --root "$ROOT_PATH" \ + --revision "$REVISION" --output "$OUTPUT_PATH" diff --git a/install-dist/scripts/dependency/test_dependency_inventory.py b/install-dist/scripts/dependency/test_dependency_inventory.py new file mode 100644 index 0000000000..65e0c6e130 --- /dev/null +++ b/install-dist/scripts/dependency/test_dependency_inventory.py @@ -0,0 +1,156 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import contextlib +import io +import os +from pathlib import Path +import shutil +import subprocess +import tempfile +import unittest +import zipfile + +import dependency_inventory as inventory + + +class DependencyInventoryTest(unittest.TestCase): + + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name) / 'checkout' + self.runtime = self.root / 'runtime' + self.runtime.mkdir(parents=True) + self.jar(self.runtime / 'resolved-1.jar') + for kind in ('server', 'pd', 'store'): + directory = self.root / ('hugegraph-' + kind) / f'apache-hugegraph-{kind}-1.7.0/lib' + directory.mkdir(parents=True) + nested = self.jar_bytes({'example/Type.class': b'class fixture'}) + self.jar(directory / 'hugegraph-executable.jar', { + 'BOOT-INF/lib/injected-2.jar': nested, + }) + + def jar_bytes(self, entries=None): + data = io.BytesIO() + with zipfile.ZipFile(data, 'w') as archive: + for name, value in (entries or {'example/Type.class': b'class fixture'}).items(): + archive.writestr(name, value) + return data.getvalue() + + def jar(self, path, entries=None): + path.write_bytes(self.jar_bytes(entries)) + + def test_runtime_and_nested_shipped_union(self): + self.assertEqual(inventory.collect(self.runtime, self.root, '1.7.0'), + {'resolved-1.jar', 'injected-2.jar'}) + + def test_missing_runtime_empty_runtime_and_package_are_failures(self): + (self.root / 'empty').mkdir() + for directory in (self.root / 'absent', self.root / 'empty'): + with self.assertRaises(inventory.InventoryFailure): + inventory.collect(directory, self.root, '1.7.0') + shutil.rmtree(self.root / 'hugegraph-store') + with self.assertRaisesRegex(inventory.InventoryFailure, 'Missing packaged store'): + inventory.collect(self.runtime, self.root, '1.7.0') + + def test_corrupt_nested_or_runtime_jar_is_failure(self): + self.jar(self.root / 'hugegraph-pd/apache-hugegraph-pd-1.7.0/lib/hugegraph-executable.jar', { + 'BOOT-INF/lib/injected-2.jar': b'not a jar', + }) + with self.assertRaisesRegex(inventory.InventoryFailure, 'Cannot inspect shipped jar'): + inventory.collect(self.runtime, self.root, '1.7.0') + (self.runtime / 'resolved-1.jar').write_text('not a jar') + with self.assertRaisesRegex(inventory.InventoryFailure, 'Cannot inspect resolved jar'): + inventory.collect(self.runtime, self.root, '1.7.0') + + def test_checker_strict_additions_removals_and_missing_inputs(self): + known, current = self.root / 'known.txt', self.root / 'current.txt' + known.write_text('one-1.jar\ntwo-2.jar\n') + current.write_text('two-2.jar\none-1.jar\n') + with contextlib.redirect_stdout(io.StringIO()): + self.assertEqual(inventory.compare(known, current), 0) + for value in ('one-1.jar\n', 'one-1.jar\ntwo-2.jar\nnew-3.jar\n'): + current.write_text(value) + self.assertEqual(inventory.compare(known, current), 1) + for value in ('', 'not-a-jar\n', 'one-1.jar\none-1.jar\n'): + current.write_text(value) + with self.assertRaises(inventory.InventoryFailure): + inventory.compare(known, current) + current.unlink() + with self.assertRaises(OSError): + inventory.compare(known, current) + + def script_fixture(self): + directory = self.root / 'install-dist/scripts/dependency' + directory.mkdir(parents=True) + original = Path(__file__).parent + for name in ('regenerate_known_dependencies.sh', 'check_dependencies.sh', 'dependency_inventory.py'): + shutil.copyfile(original / name, directory / name) + maven = self.root / 'fake-mvn' + maven.write_text('''#!/usr/bin/env python3 +import os, pathlib, sys, zipfile +if os.environ.get('FAKE_MAVEN_FAIL'): + sys.exit(int(os.environ['FAKE_MAVEN_FAIL'])) +if 'dependency:copy-dependencies' in sys.argv: + value = next(value for value in sys.argv if value.startswith('-DoutputDirectory=')) + directory = pathlib.Path(value.split('=', 1)[1]) + directory.mkdir(parents=True) + with zipfile.ZipFile(directory / 'resolved-1.jar', 'w') as archive: + archive.writestr('example/Type.class', b'class fixture') +else: + print('1.7.0') +''') + maven.chmod(0o755) + return directory, dict(os.environ, MAVEN_COMMAND=str(maven)) + + def test_shell_producer_consumer_contract(self): + directory, environment = self.script_fixture() + current = self.root / 'target/dependency/current.txt' + generated = subprocess.run(['bash', str(directory / 'regenerate_known_dependencies.sh'), str(current)], + env=environment, capture_output=True, text=True) + self.assertEqual(generated.returncode, 0, generated.stderr) + self.assertEqual(inventory.read_inventory(current), ['injected-2.jar', 'resolved-1.jar']) + known = directory / 'known-dependencies.txt' + known.write_text(current.read_text()) + checked = subprocess.run(['bash', str(directory / 'check_dependencies.sh'), str(known), str(current)], + capture_output=True, text=True) + self.assertEqual(checked.returncode, 0, checked.stderr) + current.unlink() + missing = subprocess.run(['bash', str(directory / 'check_dependencies.sh'), str(known), str(current)], + capture_output=True, text=True) + self.assertNotEqual(missing.returncode, 0) + + def test_shell_maven_failure_does_not_publish_inventory(self): + directory, environment = self.script_fixture() + current = self.root / 'current.txt' + result = subprocess.run(['bash', str(directory / 'regenerate_known_dependencies.sh'), str(current)], + env=dict(environment, FAKE_MAVEN_FAIL='17'), capture_output=True, text=True) + self.assertEqual(result.returncode, 17) + self.assertFalse(current.exists()) + + def test_shell_missing_package_does_not_publish_inventory(self): + directory, environment = self.script_fixture() + shutil.rmtree(self.root / 'hugegraph-store') + current = self.root / 'current.txt' + result = subprocess.run(['bash', str(directory / 'regenerate_known_dependencies.sh'), str(current)], + env=environment, capture_output=True, text=True) + self.assertNotEqual(result.returncode, 0) + self.assertIn('Missing packaged store', result.stderr) + self.assertFalse(current.exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/install-dist/scripts/shared-foundation/check_shared_foundation.py b/install-dist/scripts/shared-foundation/check_shared_foundation.py new file mode 100644 index 0000000000..0e6ad5c415 --- /dev/null +++ b/install-dist/scripts/shared-foundation/check_shared_foundation.py @@ -0,0 +1,466 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Check shared ownership, resolved dependencies and shipped classpaths. + +Run after a reactor install/package: + python3 install-dist/scripts/shared-foundation/check_shared_foundation.py --revision 1.8.0 + +--source-only is an explicitly narrower check for fast source-edit iterations. +The full check always regenerates dependency trees; stale tree files are not evidence. +""" + +import argparse +import io +from pathlib import Path +import re +import subprocess +import sys +import xml.etree.ElementTree as ET +import zipfile + + +SOURCE_MODULES = ( + 'hugegraph-server/hugegraph-core', + 'hugegraph-struct', + 'hugegraph-commons/hugegraph-common', + 'hugegraph-commons/hugegraph-rpc', +) +DEPENDENCY_MODULES = ( + 'hugegraph-struct', + 'hugegraph-commons/hugegraph-common', + 'hugegraph-commons/hugegraph-rpc', + 'hugegraph-pd/hg-pd-service', + 'hugegraph-store/hg-store-core', + 'hugegraph-store/hg-store-node', +) +REQUIRED_ARTIFACTS = { + 'server': {'hugegraph-core', 'hugegraph-struct', 'hugegraph-common', 'hugegraph-rpc'}, + 'pd': {'hg-pd-service', 'hg-pd-core', 'hugegraph-common'}, + 'store': {'hg-store-node', 'hg-store-core', 'hugegraph-struct', 'hugegraph-common'}, +} +SCOPES = {'compile', 'runtime', 'provided', 'test', 'system', 'import'} +GROUP = 'org.apache.hugegraph' +SERVER_ARTIFACTS = {'hugegraph-server', 'hugegraph-core', 'hugegraph-api', 'hugegraph-dist', + 'hugegraph-hstore', 'hugegraph-hbase', 'hugegraph-rocksdb', 'hugegraph-example'} +SOURCE_IMPORT_CONFIGS = ( + 'hugegraph-server/hugegraph-dist/src/assembly/static/conf/gremlin-server.yaml', + 'hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/gremlin-server.yaml', + 'hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/gremlin-server.yaml', + 'hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/gremlin-server.yaml', +) + + +class CheckFailure(Exception): + pass + + +def retired_classes(): + path = Path(__file__).with_name('retired-core-classes.txt') + result = {line.strip() for line in path.read_text().splitlines() + if line.strip() and not line.startswith('#')} + if not result or any(not name.startswith(GROUP + '.') for name in result): + raise CheckFailure(f'Missing or invalid retired-owner manifest: {path}') + return result + + +def java_member_classes(source, package): + # Strip comments/literals before matching declarations, so references to a + # retired type in documentation, strings or class literals are harmless. + source = re.sub(r'//[^\n]*|/\*.*?\*/|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'', + '', source, flags=re.DOTALL) + tokens = re.findall(r'[A-Za-z_$][\w$]*|[{}.()]', source) + scopes = [] + pending = None + names = set() + for index, token in enumerate(tokens): + if (token in ('class', 'interface', 'enum') and + (index == 0 or tokens[index - 1] != '.') and + (not scopes or scopes[-1] is not None) and index + 1 < len(tokens) and + re.fullmatch(r'[A-Za-z_$][\w$]*', tokens[index + 1])): + pending = tokens[index + 1] + elif token == '{': + scopes.append(pending) + if pending is not None: + names.add(package + '.' + '$'.join(name for name in scopes if name is not None)) + pending = None + elif token == '}' and scopes: + scopes.pop() + return names + + +def is_retired_class(name, retired): + return any(name == owner or name.startswith(owner + '$') for owner in retired) + + +def server_module_inventory(root): + boundary = (root / 'hugegraph-server').resolve() + projects, visited, active = {}, set(), set() + + def visit(pom): + try: + pom = pom.resolve() + except (OSError, RuntimeError) as error: + raise CheckFailure(f'Cannot resolve declared Server POM: {pom}: {error}') from error + try: + pom.relative_to(boundary) + except ValueError as error: + raise CheckFailure(f'Declared Server POM escapes its reactor: {pom}') from error + if pom in active: + raise CheckFailure(f'Cyclic Server module declaration: {pom}') + if pom in visited: + return + if not pom.is_file(): + raise CheckFailure(f'Missing declared Server POM: {pom}') + try: + project = ET.parse(pom).getroot() + except ET.ParseError as error: + raise CheckFailure(f'Invalid Server module POM: {pom}: {error}') from error + if project.tag.rsplit('}', 1)[-1] != 'project': + raise CheckFailure(f'Invalid Server project element: {pom}') + namespace = project.tag[:-len('project')] + artifact = (project.findtext(namespace + 'artifactId') or '').strip() + if not re.fullmatch(r'[A-Za-z0-9_.-]+', artifact): + raise CheckFailure(f'Missing or nonliteral Server artifactId: {pom}') + if pom.parent in projects and projects[pom.parent] != artifact: + raise CheckFailure(f'Server projects share a source directory: {pom.parent}') + projects[pom.parent] = artifact + active.add(pom) + # Include every possible profile, irrespective of the current host or + # active profiles. Inactive modules must not become a retirement loophole. + modules = project.findall(namespace + 'modules/' + namespace + 'module') + modules.extend(project.findall(namespace + 'profiles/' + namespace + 'profile/' + + namespace + 'modules/' + namespace + 'module')) + for declaration in modules: + value = (declaration.text or '').strip() + if not value or '$' in value: + raise CheckFailure(f'Empty or nonliteral Server module declaration: {pom}: {value}') + target = pom.parent / value + visit(target if target.suffix == '.xml' or target.is_file() else target / 'pom.xml') + active.remove(pom) + visited.add(pom) + + visit(boundary / 'pom.xml') + test_roots = [directory for directory, artifact in projects.items() if artifact == 'hugegraph-test'] + return {directory: artifact for directory, artifact in projects.items() + if not any(directory == test or test in directory.parents for test in test_roots)} + + +def check_sources(root, retired): + root = root.resolve() + owners = {} + counts = {} + production_roots = set() + for module in SOURCE_MODULES: + directories = [root / module / 'src/main' / kind for kind in ('java', 'dev')] + if not any(list(directory.rglob('*.java')) for directory in directories): + raise CheckFailure(f'Missing production sources: {root / module / "src/main"}') + production_roots.update(directories) + # Use the same recursively declared reactor inventory as shipped ownership, + # never search copied distributions or target directories for module POMs. + for module in server_module_inventory(root): + production_roots.update(module / 'src/main' / kind for kind in ('java', 'dev')) + # Generated grpc sources in src/main/java are outside the shared-owner + # scan. Hand-maintained production sources beside them must still be checked. + for pattern in ('hugegraph-*/src/main/dev', 'hugegraph-*/*/src/main/dev'): + production_roots.update(directory for directory in root.glob(pattern) + if directory.relative_to(root).parts[0] != 'hugegraph-server') + for directory in sorted(production_roots): + module = str(directory.parent.parent.parent.relative_to(root)) + files = sorted(directory.rglob('*.java')) + counts[module] = counts.get(module, 0) + len(files) + for path in files: + source = path.read_text() + package = re.search(r'^\s*package\s+([\w.]+)\s*;', source, re.MULTILINE) + if not package: + raise CheckFailure(f'Cannot determine source package: {path}') + name = package.group(1) + '.' + path.stem + if not name.startswith(GROUP + '.'): + continue + if module == 'hugegraph-server' or module.startswith('hugegraph-server/'): + declared = java_member_classes(source, package.group(1)) | {name} + if any(is_retired_class(declaration, retired) for declaration in declared): + raise CheckFailure(f'Retired shared implementation returned to Server: {path}') + if name in owners: + raise CheckFailure(f'Duplicate source FQCN {name}: {owners[name]} and {path}') + owners[name] = path + print(f'Source ownership checked: {counts}') + return owners + + +def class_imports(path): + if not path.is_file(): + raise CheckFailure(f'Missing Gremlin import configuration: {path}') + # This is a deliberately narrow reader for classImports flow/block lists, + # not a YAML implementation. Unknown shapes fail rather than evade checks. + lines = [re.sub(r'#.*$', '', line) for line in path.read_text().splitlines()] + imports = [] + for index, line in enumerate(lines): + match = re.match(r'^(\s*)classImports\s*:\s*(.*)$', line) + if not match: + continue + indent, tail = len(match.group(1)), match.group(2).strip() + if tail.startswith('['): + body = '\n'.join([tail] + lines[index + 1:]) + end = body.find(']') + if end < 0: + raise CheckFailure(f'Unterminated classImports list: {path}') + values = body[1:end].split(',') + elif not tail: + values = [] + for following in lines[index + 1:]: + if not following.strip(): + continue + following_indent = len(following) - len(following.lstrip()) + entry = following.strip() + if following_indent < indent or (following_indent == indent and not entry.startswith('-')): + break + if not entry.startswith('- '): + raise CheckFailure(f'Unsupported classImports entry: {path}: {entry}') + values.append(entry[2:]) + else: + raise CheckFailure(f'Unsupported classImports shape: {path}: {tail}') + for value in values: + name = value.strip().strip('"\'') + if not name: + continue + if not re.fullmatch(r'[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+', name): + raise CheckFailure(f'Invalid classImports class name: {path}: {name}') + imports.append(name) + if not imports: + raise CheckFailure(f'Missing or empty classImports list: {path}') + return imports + + +def check_class_imports(path, available, local_only=False): + imports = class_imports(path) + for name in imports: + # JDK classes are supplied by the runtime, not distribution jars. + # Gremlin startup tests verify runtime loading, beyond this ownership check. + if name.startswith('java.') or (local_only and not name.startswith(GROUP + '.')): + continue + if name not in available: + raise CheckFailure(f'Gremlin classImports class is unavailable: {name} ({path})') + print(f'Gremlin classImports checked: {path} ({len(imports)} imports)') + + +def check_source_imports(root, owners): + for path in SOURCE_IMPORT_CONFIGS: + check_class_imports(root / path, owners, local_only=True) + + +def parse_tree(path, expected_artifact): + if not path.is_file(): + raise CheckFailure(f'Missing resolved dependency tree: {path}') + nodes = [] + for line in path.read_text().splitlines(): + if not line.strip(): + continue + coordinate = re.sub(r'^[\s|+\\-]*', '', line).strip() + coordinate = re.sub(r' \(optional\)$', '', coordinate) + parts = coordinate.split(':') + if (len(parts) < 4 or len(parts) > 6 or + any(not part or re.search(r'\s', part) for part in parts)): + raise CheckFailure(f'Malformed resolved tree line in {path}: {line}') + if nodes and parts[-1] not in SCOPES: + raise CheckFailure(f'Missing dependency scope in {path}: {line}') + nodes.append((parts[0], parts[1])) + if not nodes or nodes[0] != (GROUP, expected_artifact): + raise CheckFailure(f'Wrong or empty dependency tree root: {path}; expected {expected_artifact}') + return nodes + + +def check_tree(path, module): + artifact = module.rsplit('/', 1)[-1] + nodes = parse_tree(path, artifact) + forbidden = set() + if module.startswith(('hugegraph-pd/', 'hugegraph-store/')): + forbidden.add('hugegraph-core') + if artifact == 'hugegraph-struct': + forbidden.update(('hugegraph-core', 'hugegraph-rpc')) + if artifact == 'hugegraph-rpc': + forbidden.update(('hugegraph-core', 'hugegraph-struct')) + if artifact == 'hugegraph-common': + forbidden.update(('hugegraph-core', 'hugegraph-struct', 'hugegraph-server', + 'hugegraph-store', 'hugegraph-pd')) + for group, name in nodes[1:]: + if group != GROUP: + continue + component_dependency = (name.startswith(('hg-pd-', 'hg-store-')) or + name in ('hugegraph-pd', 'hugegraph-store')) + if name in forbidden or (artifact in ('hugegraph-struct', 'hugegraph-common', 'hugegraph-rpc') and + component_dependency): + raise CheckFailure(f'Forbidden resolved dependency of {artifact}: {group}:{name} ({path})') + print(f'Resolved dependency boundary checked: {artifact} ({len(nodes) - 1} dependencies)') + + +def select_tree(lines, artifact): + starts = [i for i, line in enumerate(lines) if line.startswith(GROUP + ':')] + selected = [] + for index, start in enumerate(starts): + if lines[start].split(':')[1] == artifact: + stop = starts[index + 1] if index + 1 < len(starts) else len(lines) + selected.append(lines[start:stop]) + if len(selected) != 1: + raise CheckFailure(f'Expected exactly one current reactor tree for {artifact}') + return '\n'.join(selected[0]) + '\n' + + +def resolve_dependencies(root, maven): + directory = root / 'target/shared-foundation' + directory.mkdir(parents=True, exist_ok=True) + modules = set(DEPENDENCY_MODULES) + # Cover every distributed submodule, including standalone client/transfer + # modules and tests, not only dependencies currently reachable from services. + for parent in ('hugegraph-pd', 'hugegraph-store'): + modules.update(str(path.parent.relative_to(root)) + for path in (root / parent).glob('*/pom.xml')) + for module in modules: + if not (root / module / 'pom.xml').is_file(): + raise CheckFailure(f'Missing expected Maven module: {module}') + output = directory / 'reactor-dependencies.txt' + output.unlink(missing_ok=True) + # Resolve current reactor models, never reuse old tree files. Upstream + # project POMs are read from this checkout rather than a stale local install. + subprocess.run([ + maven, '-B', '-ntp', '-pl', ','.join(sorted(modules)), '-am', + 'org.apache.maven.plugins:maven-dependency-plugin:3.8.1:tree', + '-DoutputType=text', f'-DoutputFile={output}', '-DappendOutput=true', + ], cwd=root, check=True) + if not output.is_file(): + raise CheckFailure(f'Missing resolved reactor dependencies: {output}') + lines = output.read_text().splitlines() + for module in sorted(modules): + artifact = module.rsplit('/', 1)[-1] + selected = directory / (artifact + '.txt') + selected.write_text(select_tree(lines, artifact)) + check_tree(selected, module) + + +def properties(text): + return {key.strip(): value.strip() for line in text.splitlines() + if line.strip() and not line.lstrip().startswith(('#', '!')) and '=' in line + for key, value in [line.split('=', 1)]} + + +def server_artifact_ids(root): + return set(server_module_inventory(root).values()) + + +def scan_jar(source, label, owners, artifacts, retired, distribution, available=None, + expected_revision=None, server_artifacts=None): + if server_artifacts is None: + server_artifacts = SERVER_ARTIFACTS + try: + archive = zipfile.ZipFile(source) + except (OSError, zipfile.BadZipFile) as error: + raise CheckFailure(f'Invalid shipped jar {label}: {error}') from error + with archive: + names = archive.namelist() + identities = set() + for name in names: + if name.startswith('META-INF/maven/') and name.endswith('/pom.properties'): + values = properties(archive.read(name).decode('utf-8')) + if values.get('groupId') == GROUP: + artifact = values.get('artifactId') + if not artifact or not values.get('version'): + raise CheckFailure(f'Incomplete artifact metadata in {label}: {name}') + if expected_revision is not None and values['version'] != expected_revision: + raise CheckFailure(f'Stale shipped artifact {GROUP}:{artifact}:{values["version"]} ' + f'in {label}; expected {expected_revision}') + identities.add(artifact) + artifacts.update(identities) + if distribution in ('pd', 'store') and 'hugegraph-core' in identities: + raise CheckFailure(f'Forbidden hugegraph-core shipped in {distribution}: {label}') + seen_entries = set() + for name in names: + if name.startswith(('BOOT-INF/lib/', 'WEB-INF/lib/')) and name.endswith('.jar'): + scan_jar(io.BytesIO(archive.read(name)), f'{label}!/{name}', owners, + artifacts, retired, distribution, available, expected_revision, server_artifacts) + continue + normalized = re.sub(r'^(?:BOOT-INF/classes/|WEB-INF/classes/|META-INF/versions/\d+/)', '', name) + if available is not None and normalized.endswith('.class'): + available.add(normalized[:-6].replace('/', '.')) + if not normalized.startswith('org/apache/hugegraph/') or not normalized.endswith('.class'): + continue + if name in seen_entries: + raise CheckFailure(f'Duplicate class entry inside jar {label}: {name}') + seen_entries.add(name) + fqcn = normalized[:-6].replace('/', '.') + if identities & server_artifacts and is_retired_class(fqcn, retired): + raise CheckFailure(f'Retired shared class shipped in Server: {fqcn} ({label})') + previous = owners.get(fqcn) + if previous is not None and previous != label: + raise CheckFailure(f'Duplicate shipped FQCN {fqcn}: {previous} and {label}') + # Multi-release variants within the same jar are a single owner. + owners[fqcn] = label + + +def check_distribution(path, kind, retired, expected_revision=None, server_artifacts=None): + library = path / 'lib' + jars = sorted(library.rglob('*.jar')) + if not library.is_dir() or not jars: + raise CheckFailure(f'Missing shipped {kind} lib jars: {library}') + for name in ('ext', 'plugins'): + if (path / name).exists(): + jars.extend(sorted((path / name).rglob('*.jar'))) + owners = {} + artifacts = set() + available = set() + for jar in jars: + scan_jar(jar, str(jar), owners, artifacts, retired, kind, available, expected_revision, server_artifacts) + missing = REQUIRED_ARTIFACTS[kind] - artifacts + if missing: + raise CheckFailure(f'Missing expected artifacts in {kind} distribution: {sorted(missing)}') + if not owners: + raise CheckFailure(f'No HugeGraph classes found in shipped {kind} jars') + if kind == 'server': + check_class_imports(path / 'conf/gremlin-server.yaml', available) + print(f'Shipped {kind} classpath checked: {len(owners)} HugeGraph classes, ' + f'{len(artifacts)} project artifacts') + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--root', type=Path, default=Path(__file__).resolve().parents[3]) + parser.add_argument('--source-only', action='store_true') + parser.add_argument('--revision', help='Exact version of the freshly assembled distributions') + parser.add_argument('--maven', default='mvn', help='Maven executable') + args = parser.parse_args() + if not args.source_only and not args.revision: + parser.error('--revision is required for resolved dependency and distribution checks') + root = args.root.resolve() + try: + retired = retired_classes() + owners = check_sources(root, retired) + check_source_imports(root, owners) + if args.source_only: + print('Source-only check passed; dependencies and distributions were NOT checked.') + return 0 + resolve_dependencies(root, args.maven) + server_artifacts = server_artifact_ids(root) + for kind in REQUIRED_ARTIFACTS: + path = root / ('hugegraph-' + kind) / f'apache-hugegraph-{kind}-{args.revision}' + check_distribution(path, kind, retired, args.revision, server_artifacts) + except (CheckFailure, OSError, UnicodeError, subprocess.CalledProcessError) as error: + print(f'Shared foundation check FAILED: {error}', file=sys.stderr) + return 1 + print('Shared foundation ownership, resolved dependencies and shipped classpaths passed.') + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/install-dist/scripts/shared-foundation/retired-core-classes.txt b/install-dist/scripts/shared-foundation/retired-core-classes.txt new file mode 100644 index 0000000000..2aeb3c2ed0 --- /dev/null +++ b/install-dist/scripts/shared-foundation/retired-core-classes.txt @@ -0,0 +1,96 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Shared owners removed from core. Do not reintroduce these FQCNs in core. +org.apache.hugegraph.HugeException +org.apache.hugegraph.analyzer.Analyzer +org.apache.hugegraph.analyzer.AnalyzerFactory +org.apache.hugegraph.analyzer.AnsjAnalyzer +org.apache.hugegraph.analyzer.HanLPAnalyzer +org.apache.hugegraph.analyzer.IKAnalyzer +org.apache.hugegraph.analyzer.JcsegAnalyzer +org.apache.hugegraph.analyzer.JiebaAnalyzer +org.apache.hugegraph.analyzer.MMSeg4JAnalyzer +org.apache.hugegraph.analyzer.SmartCNAnalyzer +org.apache.hugegraph.auth.AuthConstant +org.apache.hugegraph.auth.TokenGenerator +org.apache.hugegraph.backend.BackendException +org.apache.hugegraph.backend.id.EdgeId +org.apache.hugegraph.backend.id.Id +org.apache.hugegraph.backend.id.IdGenerator +org.apache.hugegraph.backend.id.IdUtil +org.apache.hugegraph.backend.id.SplicingIdGenerator +org.apache.hugegraph.backend.query.Aggregate +org.apache.hugegraph.backend.query.BatchConditionQuery +org.apache.hugegraph.backend.query.Condition +org.apache.hugegraph.backend.query.ConditionQuery +org.apache.hugegraph.backend.query.IdPrefixQuery +org.apache.hugegraph.backend.query.IdQuery +org.apache.hugegraph.backend.query.IdRangeQuery +org.apache.hugegraph.backend.query.Query +org.apache.hugegraph.backend.query.serializer.AbstractSerializerAdapter +org.apache.hugegraph.backend.query.serializer.QueryAdapter +org.apache.hugegraph.backend.query.serializer.QueryIdAdapter +org.apache.hugegraph.backend.serializer.BytesBuffer +org.apache.hugegraph.backend.store.BackendEntry$BackendColumn +org.apache.hugegraph.backend.store.Shard +org.apache.hugegraph.backend.tx.GraphIndexTransaction$MatchedIndex +org.apache.hugegraph.exception.ErrorCodeProvider +org.apache.hugegraph.exception.LimitExceedException +org.apache.hugegraph.exception.NotAllowException +org.apache.hugegraph.exception.NotFoundException +org.apache.hugegraph.exception.NotSupportException +org.apache.hugegraph.rpc.RpcServiceConfig4Client +org.apache.hugegraph.rpc.RpcServiceConfig4Server +org.apache.hugegraph.schema.EdgeLabel +org.apache.hugegraph.schema.IndexLabel +org.apache.hugegraph.schema.PropertyKey +org.apache.hugegraph.schema.SchemaElement +org.apache.hugegraph.schema.SchemaLabel +org.apache.hugegraph.schema.Userdata +org.apache.hugegraph.schema.VertexLabel +org.apache.hugegraph.schema.builder.SchemaBuilder +org.apache.hugegraph.structure.GraphType +org.apache.hugegraph.structure.HugeIndex +org.apache.hugegraph.type.HugeType +org.apache.hugegraph.type.Idfiable +org.apache.hugegraph.type.Indexable +org.apache.hugegraph.type.Nameable +org.apache.hugegraph.type.Propertiable +org.apache.hugegraph.type.Typeable +org.apache.hugegraph.type.define.Action +org.apache.hugegraph.type.define.AggregateType +org.apache.hugegraph.type.define.Cardinality +org.apache.hugegraph.type.define.CollectionType +org.apache.hugegraph.type.define.DataType +org.apache.hugegraph.type.define.Directions +org.apache.hugegraph.type.define.EdgeLabelType +org.apache.hugegraph.type.define.Frequency +org.apache.hugegraph.type.define.HugeKeys +org.apache.hugegraph.type.define.IdStrategy +org.apache.hugegraph.type.define.IndexType +org.apache.hugegraph.type.define.SchemaStatus +org.apache.hugegraph.type.define.SerialEnum +org.apache.hugegraph.type.define.WriteType +org.apache.hugegraph.util.Blob +org.apache.hugegraph.util.KryoUtil +org.apache.hugegraph.util.LZ4Util +org.apache.hugegraph.util.StringEncoding +org.apache.hugegraph.util.collection.CollectionFactory +org.apache.hugegraph.util.collection.IdSet +org.apache.hugegraph.util.collection.IntIterator +org.apache.hugegraph.util.collection.IntMap +org.apache.hugegraph.util.collection.IntSet diff --git a/install-dist/scripts/shared-foundation/test_shared_foundation.py b/install-dist/scripts/shared-foundation/test_shared_foundation.py new file mode 100644 index 0000000000..0707f22afc --- /dev/null +++ b/install-dist/scripts/shared-foundation/test_shared_foundation.py @@ -0,0 +1,638 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import io +from pathlib import Path +import tempfile +import unittest +import xml.etree.ElementTree as ET +import zipfile + +import check_shared_foundation as check + + +class FoundationChecksTest(unittest.TestCase): + + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.root = Path(self.temporary.name) + self.addCleanup(self.temporary.cleanup) + + def jar(self, artifact, classes=(), entries=None, version='1.8.0', group=check.GROUP): + buffer = io.BytesIO() + with zipfile.ZipFile(buffer, 'w') as archive: + archive.writestr(f'META-INF/maven/{group}/{artifact}/pom.properties', + f'groupId={group}\nartifactId={artifact}\nversion={version}\n') + for name in classes: + archive.writestr(name, b'class fixture') + for name, value in (entries or {}).items(): + archive.writestr(name, value) + return buffer.getvalue() + + def distribution(self, kind='server', nested=False): + path = self.root / kind + (path / 'lib').mkdir(parents=True) + jars = {} + for artifact in check.REQUIRED_ARTIFACTS[kind]: + name = artifact.replace('-', '_') + jars[artifact] = self.jar(artifact, [f'org/apache/hugegraph/{name}.class']) + if nested: + executable = 'hg-pd-service' if kind == 'pd' else 'hg-store-node' + entries = {f'BOOT-INF/lib/{name}.jar': value for name, value in jars.items() + if name != executable} + data = self.jar(executable, [f'BOOT-INF/classes/org/apache/hugegraph/{executable}.class'], entries) + (path / 'lib' / 'service.jar').write_bytes(data) + else: + for name, value in jars.items(): + (path / 'lib' / (name + '.jar')).write_bytes(value) + if kind == 'server': + (path / 'conf').mkdir() + (path / 'conf/gremlin-server.yaml').write_text( + 'classImports: [org.apache.hugegraph.hugegraph_core]\n') + return path + + def tree(self, artifact, descendants=''): + path = self.root / 'tree.txt' + path.write_text(f'{check.GROUP}:{artifact}:jar:1.8.0\n' + descendants) + return path + + def test_shipped_classpaths_flat_and_boot(self): + for kind in ('server', 'pd', 'store'): + check.check_distribution(self.distribution(kind, nested=kind != 'server'), kind, set()) + + def test_duplicate_class_in_two_shipped_jars_fails(self): + path = self.distribution() + (path / 'lib' / 'copy.jar').write_bytes(self.jar('copy', ['org/apache/hugegraph/hugegraph_struct.class'])) + with self.assertRaisesRegex(check.CheckFailure, 'Duplicate shipped FQCN'): + check.check_distribution(path, 'server', set()) + + def test_duplicate_in_nested_boot_jar_fails(self): + duplicate = 'org/apache/hugegraph/Conflict.class' + jars = {f'BOOT-INF/lib/{name}.jar': self.jar(name, [duplicate]) for name in ('one', 'two')} + path = self.root / 'boot.jar' + path.write_bytes(self.jar('boot', entries=jars)) + with self.assertRaisesRegex(check.CheckFailure, 'Duplicate shipped FQCN'): + check.scan_jar(path, str(path), {}, set(), set(), 'pd') + + def test_multi_release_variants_in_one_jar_are_one_owner(self): + path = self.root / 'mr.jar' + path.write_bytes(self.jar('variant', ['org/apache/hugegraph/Variant.class', + 'META-INF/versions/11/org/apache/hugegraph/Variant.class'])) + owners = {} + check.scan_jar(path, str(path), owners, set(), set(), 'server') + self.assertEqual(list(owners), ['org.apache.hugegraph.Variant']) + + def test_missing_distribution_and_required_artifact_fail_closed(self): + with self.assertRaisesRegex(check.CheckFailure, 'Missing shipped'): + check.check_distribution(self.root / 'absent', 'server', set()) + path = self.distribution() + (path / 'lib' / 'hugegraph-struct.jar').unlink() + with self.assertRaisesRegex(check.CheckFailure, 'Missing expected artifacts'): + check.check_distribution(path, 'server', set()) + + def test_corrupt_jar_is_failure(self): + path = self.distribution() + (path / 'lib' / 'broken.jar').write_text('not a zip') + with self.assertRaisesRegex(check.CheckFailure, 'Invalid shipped jar'): + check.check_distribution(path, 'server', set()) + + def test_nested_core_shipped_with_pd_is_failure(self): + path = self.distribution('pd', nested=True) + (path / 'lib' / 'extra.jar').write_bytes(self.jar('extra', entries={ + 'BOOT-INF/lib/core.jar': self.jar('hugegraph-core', ['org/apache/hugegraph/Core.class']) + })) + with self.assertRaisesRegex(check.CheckFailure, 'Forbidden hugegraph-core shipped'): + check.check_distribution(path, 'pd', set()) + + def test_transitive_forbidden_dependencies_fail(self): + for module, forbidden in (('hugegraph-pd/hg-pd-service', 'hugegraph-core'), + ('hugegraph-store/hg-store-core', 'hugegraph-core'), + ('hugegraph-struct', 'hg-pd-client'), + ('hugegraph-struct', 'hugegraph-core'), + ('hugegraph-commons/hugegraph-common', 'hg-store-client')): + with self.subTest(module=module, forbidden=forbidden): + artifact = module.rsplit('/', 1)[-1] + descendants = (f'+- external:parent:jar:1.0:compile\n' + f'| \\- {check.GROUP}:{forbidden}:jar:1.8.0:compile\n') + with self.assertRaisesRegex(check.CheckFailure, 'Forbidden resolved dependency'): + check.check_tree(self.tree(artifact, descendants), module) + + def test_struct_rejects_all_pd_store_component_dependencies(self): + for name in ('hg-pd-service', 'hg-store-common', 'hugegraph-pd', 'hugegraph-store'): + for prefix in ('', '+- external:parent:jar:1.0:compile\n| '): + with self.subTest(name=name, transitive=bool(prefix)): + descendants = prefix + f'\\- {check.GROUP}:{name}:jar:1.8.0:compile\n' + with self.assertRaisesRegex(check.CheckFailure, 'Forbidden resolved dependency'): + check.check_tree(self.tree('hugegraph-struct', descendants), 'hugegraph-struct') + # The boundary concerns HugeGraph components, not similarly named external artifacts. + tree = self.tree('hugegraph-struct', '\\- external:hg-pd-service:jar:1.0:compile\n') + check.check_tree(tree, 'hugegraph-struct') + + def test_allowed_kryo_dependency_and_classifier(self): + tree = self.tree('hugegraph-struct', '\\- org.apache.tinkerpop:gremlin-shaded:jar:1.0:compile\n' + '+- external:native:jar:linux:1.0:runtime (optional)\n') + check.check_tree(tree, 'hugegraph-struct') + + def test_missing_wrong_or_malformed_tree_fails_closed(self): + with self.assertRaisesRegex(check.CheckFailure, 'Missing resolved'): + check.parse_tree(self.root / 'absent', 'hugegraph-struct') + for value in ('', 'this is a Maven error\n', f'{check.GROUP}:wrong:jar:1.8.0\n', + f'{check.GROUP}:hugegraph-struct:jar:1.8.0\n+- broken:data\n'): + path = self.root / 'bad.txt' + path.write_text(value) + with self.subTest(value=value), self.assertRaises(check.CheckFailure): + check.parse_tree(path, 'hugegraph-struct') + + def sources(self): + self.declare_server_module('hugegraph-core') + for index, module in enumerate(check.SOURCE_MODULES): + path = self.root / module / 'src/main/java/org/apache/hugegraph' / f'Unique{index}.java' + path.parent.mkdir(parents=True) + path.write_text(f'package org.apache.hugegraph;\npublic class Unique{index} {{}}\n') + + def declare_server_module(self, module): + namespace = '{http://maven.apache.org/POM/4.0.0}' + root = self.root / 'hugegraph-server' + root.mkdir(exist_ok=True) + pom = root / 'pom.xml' + if not pom.exists(): + pom.write_text('' + 'hugegraph-server') + tree = ET.parse(pom) + modules = tree.getroot().find(namespace + 'modules') + if module not in [entry.text for entry in modules]: + ET.SubElement(modules, namespace + 'module').text = module + tree.write(pom, encoding='unicode') + child = root / module / 'pom.xml' + child.parent.mkdir(parents=True, exist_ok=True) + if not child.exists(): + child.write_text('' + '' + Path(module).name + '') + return child + + def test_target_reactor_tree_must_exist_exactly_once(self): + lines = ['org.apache.hugegraph:hugegraph: pom:1.8.0'.replace(': ', ':'), + 'org.apache.hugegraph:hugegraph-struct:jar:1.8.0', + '+- external:one:jar:1.0:compile', + 'org.apache.hugegraph:hg-store-core:jar:1.8.0', + '\\- org.apache.hugegraph:hugegraph-struct:jar:1.8.0:compile'] + self.assertEqual(check.select_tree(lines, 'hugegraph-struct'), '\n'.join(lines[1:3]) + '\n') + with self.assertRaisesRegex(check.CheckFailure, 'exactly one'): + check.select_tree(lines, 'missing') + with self.assertRaisesRegex(check.CheckFailure, 'exactly one'): + check.select_tree(lines + lines[1:3], 'hugegraph-struct') + + def test_source_duplicates_and_retired_owner_are_rejected(self): + self.sources() + check.check_sources(self.root, set()) + path = self.root / check.SOURCE_MODULES[1] / 'src/main/java/org/apache/hugegraph/Unique0.java' + path.write_text('package org.apache.hugegraph;\npublic class Unique0 {}\n') + with self.assertRaisesRegex(check.CheckFailure, 'Duplicate source FQCN'): + check.check_sources(self.root, set()) + path.unlink() + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, {'org.apache.hugegraph.Unique0'}) + + def test_manual_dev_sources_cannot_duplicate_shared_owners(self): + self.sources() + # Both the shared modules' alternate source roots and hand-maintained + # grpc helpers are production input, unlike generated grpc Java sources. + for module in (check.SOURCE_MODULES[1], 'hugegraph-store/hg-store-grpc'): + with self.subTest(module=module): + path = self.root / module / 'src/main/dev/org/apache/hugegraph/Unique0.java' + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text('package org.apache.hugegraph;\npublic class Unique0 {}\n') + with self.assertRaisesRegex(check.CheckFailure, 'Duplicate source FQCN'): + check.check_sources(self.root, set()) + path.unlink() + + def test_server_api_backend_and_dist_source_duplicates_are_rejected(self): + self.sources() + for module in ('hugegraph-api', 'hugegraph-hstore', 'hugegraph-dist'): + self.declare_server_module(module) + with self.subTest(module=module): + path = (self.root / 'hugegraph-server' / module / + 'src/main/java/org/apache/hugegraph/Unique0.java') + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text('package org.apache.hugegraph;\npublic class Unique0 {}\n') + with self.assertRaisesRegex(check.CheckFailure, 'Duplicate source FQCN'): + check.check_sources(self.root, set()) + path.unlink() + self.declare_server_module('hugegraph-test') + fixture = (self.root / 'hugegraph-server/hugegraph-test/' + 'src/main/java/org/apache/hugegraph/Unique0.java') + fixture.parent.mkdir(parents=True) + fixture.write_text('package org.apache.hugegraph;\npublic class Unique0 {}\n') + check.check_sources(self.root, set()) + + def test_retired_owner_cannot_return_through_core_dev_sources(self): + self.sources() + path = self.root / check.SOURCE_MODULES[0] / 'src/main/dev/org/apache/hugegraph/Retired.java' + path.parent.mkdir(parents=True) + path.write_text('package org.apache.hugegraph;\npublic class Retired {}\n') + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, {'org.apache.hugegraph.Retired'}) + + def test_retired_owner_in_core_jar_is_rejected(self): + retired = check.retired_classes() + for name in ('org.apache.hugegraph.backend.id.Id', 'org.apache.hugegraph.backend.store.Shard'): + with self.subTest(name=name): + self.assertIn(name, retired) + path = self.root / 'core.jar' + entry = name.replace('.', '/') + '$Inner.class' + path.write_bytes(self.jar('hugegraph-core', [entry])) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared class shipped'): + check.scan_jar(path, str(path), {}, set(), retired, 'server') + + def test_canonical_shard_allowed_and_old_core_owner_rejected(self): + self.sources() + retired = check.retired_classes() + relative = 'src/main/java/org/apache/hugegraph/backend/Shard.java' + canonical = self.root / 'hugegraph-struct' / relative + canonical.parent.mkdir(parents=True) + canonical.write_text('package org.apache.hugegraph.backend;\npublic class Shard {}\n') + check.check_sources(self.root, retired) + old = (self.root / check.SOURCE_MODULES[0] / + 'src/main/java/org/apache/hugegraph/backend/store/Shard.java') + old.parent.mkdir(parents=True) + old.write_text('package org.apache.hugegraph.backend.store;\npublic class Shard {}\n') + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, retired) + + def test_retired_nested_source_owner_preserves_entry_and_iterators(self): + self.sources() + retired = check.retired_classes() + owner = 'org.apache.hugegraph.backend.store.BackendEntry$BackendColumn' + self.assertIn(owner, retired) + path = (self.root / check.SOURCE_MODULES[0] / + 'src/main/java/org/apache/hugegraph/backend/store/BackendEntry.java') + path.parent.mkdir(parents=True) + source = '''package org.apache.hugegraph.backend.store; +interface BackendEntry { + String text = "class BackendColumn {}"; + // class BackendColumn {} + Class reference = Other.BackendColumn.class; + interface BackendColumnIterator { class EmptyIterator {} } + class Other { class BackendColumn {} } + default void example() { class BackendColumn {} } +} +''' + path.write_text(source) + check.check_sources(self.root, retired) + for declaration in ('class BackendColumn {}', 'interface BackendColumn {}', + 'enum BackendColumn { VALUE }'): + with self.subTest(declaration=declaration): + path.write_text(source.replace('interface BackendEntry {', + 'interface BackendEntry {\n' + declaration)) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, retired) + + def test_retired_nested_jar_owner_preserves_entry_and_iterators(self): + retired = check.retired_classes() + prefix = 'org/apache/hugegraph/backend/store/BackendEntry' + path = self.root / 'core.jar' + allowed = [prefix + suffix + '.class' for suffix in + ('', '$BackendColumnIterator', '$BackendColumnIterator$EmptyIterator', + '$Other$BackendColumn')] + path.write_bytes(self.jar('hugegraph-core', allowed)) + check.scan_jar(path, str(path), {}, set(), retired, 'server') + for suffix in ('$BackendColumn', '$BackendColumn$Child'): + with self.subTest(suffix=suffix): + path.write_bytes(self.jar('hugegraph-core', allowed + [prefix + suffix + '.class'])) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared class shipped'): + check.scan_jar(path, str(path), {}, set(), retired, 'server') + + def test_retired_index_sources_preserve_transaction_and_shared_models(self): + self.sources() + retired = check.retired_classes() + self.assertIn('org.apache.hugegraph.structure.HugeIndex', retired) + self.assertIn('org.apache.hugegraph.backend.tx.GraphIndexTransaction$MatchedIndex', retired) + for package, name in (('structure', 'Index'), ('query', 'MatchedIndex')): + path = (self.root / 'hugegraph-struct/src/main/java/org/apache/hugegraph' / + package / (name + '.java')) + path.parent.mkdir(parents=True) + path.write_text(f'package org.apache.hugegraph.{package};\npublic class {name} {{}}\n') + transaction = (self.root / check.SOURCE_MODULES[0] / + 'src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java') + transaction.parent.mkdir(parents=True) + source = '''package org.apache.hugegraph.backend.tx; +class GraphIndexTransaction { + String text = "class MatchedIndex {}"; + class MatchedIndexIterator {} + class Other { class MatchedIndex {} } +} +''' + transaction.write_text(source) + check.check_sources(self.root, retired) + huge_index = (self.root / check.SOURCE_MODULES[0] / + 'src/main/java/org/apache/hugegraph/structure/HugeIndex.java') + huge_index.parent.mkdir(parents=True) + huge_index.write_text('package org.apache.hugegraph.structure;\nclass HugeIndex {}\n') + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, retired) + huge_index.unlink() + transaction.write_text(source.replace('class GraphIndexTransaction {', + 'class GraphIndexTransaction {\nprivate static class MatchedIndex {}')) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, retired) + + def test_retired_index_bytecode_including_children_is_rejected(self): + retired = check.retired_classes() + path = self.root / 'core.jar' + transaction = 'org/apache/hugegraph/backend/tx/GraphIndexTransaction' + allowed = [transaction + suffix + '.class' for suffix in + ('', '$MatchedIndexIterator', '$Other$MatchedIndex')] + path.write_bytes(self.jar('hugegraph-core', allowed)) + check.scan_jar(path, str(path), {}, set(), retired, 'server') + shared = self.root / 'struct.jar' + shared.write_bytes(self.jar('hugegraph-struct', ['org/apache/hugegraph/structure/Index.class', + 'org/apache/hugegraph/query/MatchedIndex.class'])) + check.scan_jar(shared, str(shared), {}, set(), retired, 'server') + for name in ('org/apache/hugegraph/structure/HugeIndex', + 'org/apache/hugegraph/structure/HugeIndex$IdWithExpiredTime', + transaction + '$MatchedIndex', transaction + '$MatchedIndex$Child'): + with self.subTest(name=name): + path.write_bytes(self.jar('hugegraph-core', allowed + [name + '.class'])) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared class shipped'): + check.scan_jar(path, str(path), {}, set(), retired, 'server') + + def test_rpc_interfaces_owned_by_common_not_core_or_rpc_implementation(self): + self.sources() + retired = check.retired_classes() + for name in ('RpcServiceConfig4Client', 'RpcServiceConfig4Server'): + relative = 'src/main/java/org/apache/hugegraph/rpc/' + name + '.java' + source = f'package org.apache.hugegraph.rpc;\npublic interface {name} {{}}\n' + common = self.root / 'hugegraph-commons/hugegraph-common' / relative + common.parent.mkdir(parents=True, exist_ok=True) + common.write_text(source) + self.assertIn('org.apache.hugegraph.rpc.' + name, retired) + check.check_sources(self.root, retired) + for module, message in ((check.SOURCE_MODULES[0], 'Retired shared implementation'), + ('hugegraph-commons/hugegraph-rpc', 'Duplicate source FQCN')): + with self.subTest(name=name, module=module): + duplicate = self.root / module / relative + duplicate.parent.mkdir(parents=True, exist_ok=True) + duplicate.write_text(source) + with self.assertRaisesRegex(check.CheckFailure, message): + check.check_sources(self.root, retired) + duplicate.unlink() + + def test_all_source_gremlin_configs_resolve_current_shared_class_names(self): + current = 'org.apache.hugegraph.id.IdGenerator' + directions = 'org.apache.hugegraph.type.define.Directions' + for relative in check.SOURCE_IMPORT_CONFIGS: + path = self.root / relative + path.parent.mkdir(parents=True) + path.write_text(f'classImports: [{current}, {directions}, java.lang.Math]\n') + check.check_source_imports(self.root, {current, directions}) + path = self.root / check.SOURCE_IMPORT_CONFIGS[-1] + path.write_text('classImports: [org.apache.hugegraph.backend.id.IdGenerator]\n') + with self.assertRaisesRegex(check.CheckFailure, 'class is unavailable'): + check.check_source_imports(self.root, {current, directions}) + path.unlink() + with self.assertRaisesRegex(check.CheckFailure, 'Missing Gremlin import configuration'): + check.check_source_imports(self.root, {current, directions}) + + def test_gremlin_import_reader_flow_and_block_lists(self): + path = self.root / 'gremlin.yaml' + path.write_text('classImports: [\n "example.One", # first import\n\'example.Two\', java.lang.Math\n]\n') + self.assertEqual(check.class_imports(path), ['example.One', 'example.Two', 'java.lang.Math']) + path.write_text('plugins:\n classImports:\n - "example.One"\n - \'example.Two\'\n' + ' methodImports: [example.One#*]\n') + self.assertEqual(check.class_imports(path), ['example.One', 'example.Two']) + for value in ('classImports: *alias\n', 'classImports: [example.One\n', + 'classImports: [example.*]\n', 'classImports: []\n'): + with self.subTest(value=value): + path.write_text(value) + with self.assertRaises(check.CheckFailure): + check.class_imports(path) + + def test_packaged_gremlin_imports_resolve_shared_and_external_classes(self): + path = self.distribution() + (path / 'lib/hugegraph-struct.jar').write_bytes(self.jar('hugegraph-struct', [ + 'org/apache/hugegraph/id/IdGenerator.class', 'org/apache/hugegraph/type/define/Directions.class' + ])) + (path / 'lib/external.jar').write_bytes(self.jar('external', entries={ + 'BOOT-INF/lib/inner.jar': self.jar('external-inner', ['example/External.class']) + })) + config = path / 'conf/gremlin-server.yaml' + config.write_text('classImports: [org.apache.hugegraph.id.IdGenerator,\n' + 'org.apache.hugegraph.type.define.Directions, example.External, java.lang.Math]\n') + check.check_distribution(path, 'server', check.retired_classes()) + config.write_text('classImports: [org.apache.hugegraph.backend.id.IdGenerator]\n') + with self.assertRaisesRegex(check.CheckFailure, 'class is unavailable'): + check.check_distribution(path, 'server', check.retired_classes()) + config.unlink() + with self.assertRaisesRegex(check.CheckFailure, 'Missing Gremlin import configuration'): + check.check_distribution(path, 'server', check.retired_classes()) + + def test_forbidden_dependencies_are_matched_by_exact_group(self): + for module in ('hugegraph-struct', 'hugegraph-commons/hugegraph-common', + 'hugegraph-commons/hugegraph-rpc', 'hugegraph-pd/hg-pd-service', + 'hugegraph-store/hg-store-core'): + artifact = module.rsplit('/', 1)[-1] + with self.subTest(module=module): + tree = self.tree(artifact, '\\- external:hugegraph-core:jar:1.0:compile\n') + check.check_tree(tree, module) + tree = self.tree(artifact, f'\\- {check.GROUP}:hugegraph-core:jar:1.8.0:compile\n') + with self.assertRaisesRegex(check.CheckFailure, 'Forbidden resolved dependency'): + check.check_tree(tree, module) + + def test_struct_and_rpc_framework_dependency_boundaries(self): + module = 'hugegraph-commons/hugegraph-rpc' + self.assertIn(module, check.DEPENDENCY_MODULES) + targets = [('hugegraph-struct', 'hugegraph-rpc')] + targets.extend((module, name) for name in ('hugegraph-core', 'hugegraph-struct', 'hg-pd-client', + 'hg-store-common', 'hugegraph-pd', 'hugegraph-store')) + for caller, dependency in targets: + artifact = caller.rsplit('/', 1)[-1] + for prefix in ('', '+- external:parent:jar:1.0:compile\n| '): + with self.subTest(caller=caller, dependency=dependency, transitive=bool(prefix)): + tree = self.tree(artifact, prefix + f'\\- {check.GROUP}:{dependency}:jar:1.8.0:compile\n') + with self.assertRaisesRegex(check.CheckFailure, 'Forbidden resolved dependency'): + check.check_tree(tree, caller) + check.check_tree(self.tree('hugegraph-rpc', f'\\- {check.GROUP}:hugegraph-common:jar:1.8.0:compile\n'), module) + + def test_stale_project_versions_in_direct_and_nested_distributions_fail(self): + for kind in ('server', 'pd', 'store'): + with self.subTest(kind=kind): + path = self.distribution(kind, nested=kind != 'server') + check.check_distribution(path, kind, set(), expected_revision='1.8.0') + extra = path / 'lib/extra.jar' + stale = self.jar('stale-helper', ['org/apache/hugegraph/Stale.class'], version='1.7.0') + extra.write_bytes(stale) + with self.assertRaisesRegex(check.CheckFailure, 'Stale shipped artifact'): + check.check_distribution(path, kind, set(), expected_revision='1.8.0') + extra.write_bytes(self.jar('boot-helper', entries={'BOOT-INF/lib/stale.jar': stale})) + with self.assertRaisesRegex(check.CheckFailure, 'Stale shipped artifact'): + check.check_distribution(path, kind, set(), expected_revision='1.8.0') + extra.write_bytes(self.jar('hugegraph-core', ['example/External.class'], + group='external', version='9.0')) + check.check_distribution(path, kind, set(), expected_revision='1.8.0') + + def test_retired_sources_cannot_return_in_server_api_or_backends(self): + self.sources() + retired = check.retired_classes() + # Canonical owners preserve their original FQCNs even though those + # implementations were removed from Server; their imports/aliases stay legal. + for module, package, name in (('hugegraph-struct', 'type', 'HugeType'), + ('hugegraph-commons/hugegraph-common', 'auth', 'TokenGenerator')): + path = self.root / module / 'src/main/java/org/apache/hugegraph' / package / (name + '.java') + path.parent.mkdir(parents=True) + path.write_text(f'package org.apache.hugegraph.{package};\npublic class {name} {{}}\n') + check.check_sources(self.root, retired) + for module in ('hugegraph-api', 'hugegraph-hstore'): + self.declare_server_module(module) + path = (self.root / 'hugegraph-server' / module / + 'src/main/java/org/apache/hugegraph/backend/id/Id.java') + path.parent.mkdir(parents=True) + path.write_text('package org.apache.hugegraph.backend.id;\npublic interface Id {}\n') + with self.subTest(module=module), self.assertRaisesRegex(check.CheckFailure, + 'Retired shared implementation'): + check.check_sources(self.root, retired) + path.unlink() + nested = (self.root / 'hugegraph-server' / module / + 'src/main/java/org/apache/hugegraph/backend/store/BackendEntry.java') + nested.parent.mkdir(parents=True) + nested.write_text('package org.apache.hugegraph.backend.store;\n' + 'interface BackendEntry { class BackendColumn {} }\n') + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared implementation'): + check.check_sources(self.root, retired) + nested.write_text('package org.apache.hugegraph.backend.store;\n' + 'interface BackendEntry { String alias = "class BackendColumn {}"; }\n') + check.check_sources(self.root, retired) + nested.unlink() + self.declare_server_module('hugegraph-test') + fixture = (self.root / 'hugegraph-server/hugegraph-test/' + 'src/main/java/org/apache/hugegraph/backend/id/Id.java') + fixture.parent.mkdir(parents=True) + fixture.write_text('package org.apache.hugegraph.backend.id;\ninterface Id {}\n') + check.check_sources(self.root, retired) + + def test_retired_bytecode_cannot_return_in_any_server_artifact(self): + retired = check.retired_classes() + jar = self.root / 'owner.jar' + for artifact in check.SERVER_ARTIFACTS: + for name in ('org/apache/hugegraph/backend/id/Id.class', + 'org/apache/hugegraph/backend/store/BackendEntry$BackendColumn.class'): + with self.subTest(artifact=artifact, name=name): + jar.write_bytes(self.jar(artifact, [name])) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared class shipped'): + check.scan_jar(jar, str(jar), {}, set(), retired, 'server') + for artifact, name in (('hugegraph-struct', 'org/apache/hugegraph/type/HugeType.class'), + ('hugegraph-common', 'org/apache/hugegraph/auth/TokenGenerator.class'), + ('hugegraph-test', 'org/apache/hugegraph/backend/id/Id.class')): + jar.write_bytes(self.jar(artifact, [name])) + check.scan_jar(jar, str(jar), {}, set(), retired, 'server') + + def test_new_server_module_artifacts_are_included_in_retirement_policy(self): + self.declare_server_module('new-backend') + ids = check.server_artifact_ids(self.root) + self.assertIn('new-backend', ids) + jar = self.root / 'new.jar' + jar.write_bytes(self.jar('new-backend', ['org/apache/hugegraph/backend/id/Id.class'])) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared class shipped'): + check.scan_jar(jar, str(jar), {}, set(), check.retired_classes(), 'server', server_artifacts=ids) + + def test_nested_profile_module_sources_and_shipped_artifacts_are_checked(self): + self.sources() + aggregator = self.declare_server_module('backend') + aggregator.write_text('' + 'backend-parentfuture-platform' + 'new-backend') + module = aggregator.parent / 'new-backend' + module.mkdir() + (module / 'pom.xml').write_text('' + 'future-server-backend') + identities = check.server_artifact_ids(self.root) + self.assertIn('future-server-backend', identities) + retired = check.retired_classes() + for kind in ('java', 'dev'): + path = module / 'src/main' / kind / 'org/apache/hugegraph/backend/id/Id.java' + path.parent.mkdir(parents=True) + path.write_text('package org.apache.hugegraph.backend.id;\ninterface Id {}\n') + with self.subTest(kind=kind), self.assertRaisesRegex(check.CheckFailure, + 'Retired shared implementation'): + check.check_sources(self.root, retired) + path.unlink() + alias = module / 'src/main/java/org/apache/hugegraph/backend/NewBackend.java' + alias.write_text('package org.apache.hugegraph.backend;\n' + 'class NewBackend { String legacy = "org.apache.hugegraph.backend.id.Id"; }\n') + check.check_sources(self.root, retired) + jar = self.root / 'nested-backend.jar' + data = self.jar('future-server-backend', ['org/apache/hugegraph/backend/id/Id.class']) + for value in (data, self.jar('boot-wrapper', entries={'BOOT-INF/lib/backend.jar': data})): + jar.write_bytes(value) + with self.assertRaisesRegex(check.CheckFailure, 'Retired shared class shipped'): + check.scan_jar(jar, str(jar), {}, set(), retired, 'server', server_artifacts=identities) + + def test_declared_reactor_failures_are_closed(self): + self.sources() + aggregator = self.declare_server_module('backend') + cases = (('missing-child', 'Missing declared Server POM'), + ('../', 'Cyclic Server module declaration'), + ('../../outside-server', 'escapes its reactor'), + ('${unknown.module}', 'nonliteral Server module declaration'), + ('', 'Empty or nonliteral Server module declaration')) + for value, message in cases: + with self.subTest(module=value): + aggregator.write_text('backend-parent' + '' + value + '') + with self.assertRaisesRegex(check.CheckFailure, message): + check.server_module_inventory(self.root) + aggregator.write_text('backend-parent') + with self.assertRaisesRegex(check.CheckFailure, 'Invalid Server module POM'): + check.server_module_inventory(self.root) + aggregator.unlink() + with self.assertRaisesRegex(check.CheckFailure, 'Missing declared Server POM'): + check.server_module_inventory(self.root) + + def test_reactor_inventory_ignores_unlisted_copied_and_target_modules(self): + self.sources() + for relative in ('target/copied-backend', 'apache-hugegraph-server-1.8.0'): + directory = self.root / 'hugegraph-server' / relative + source = directory / 'src/main/dev/org/apache/hugegraph/backend/id/Id.java' + source.parent.mkdir(parents=True) + source.write_text('package org.apache.hugegraph.backend.id;\ninterface Id {}\n') + (directory / 'pom.xml').write_text('unlisted-copy') + check.check_sources(self.root, check.retired_classes()) + self.assertNotIn('unlisted-copy', check.server_artifact_ids(self.root)) + + def test_profile_redeclarations_deduplicate_and_test_subtree_is_excluded(self): + self.sources() + test = self.declare_server_module('hugegraph-test') + test.write_text('hugegraph-test' + 'fixtures') + child = test.parent / 'fixtures' + child.mkdir() + (child / 'pom.xml').write_text('test-fixtures') + path = child / 'src/main/java/org/apache/hugegraph/backend/id/Id.java' + path.parent.mkdir(parents=True) + path.write_text('package org.apache.hugegraph.backend.id;\ninterface Id {}\n') + root_pom = self.root / 'hugegraph-server/pom.xml' + project = ET.parse(root_pom) + namespace = '{http://maven.apache.org/POM/4.0.0}' + profiles = ET.SubElement(project.getroot(), namespace + 'profiles') + profile = ET.SubElement(profiles, namespace + 'profile') + modules = ET.SubElement(profile, namespace + 'modules') + ET.SubElement(modules, namespace + 'module').text = './hugegraph-core' + project.write(root_pom, encoding='unicode') + check.check_sources(self.root, check.retired_classes()) + identities = check.server_artifact_ids(self.root) + self.assertEqual(identities, {'hugegraph-server', 'hugegraph-core'}) + + +if __name__ == '__main__': + unittest.main() From 67dbaf6fd40985817501debe2d944b5d87d65ff3 Mon Sep 17 00:00:00 2001 From: imbajin Date: Thu, 1 Oct 2026 11:29:46 +0800 Subject: [PATCH 02/11] fix: preserve migration build and license checks - retain the original ASF header and third-party source attribution - run historical Store ingress tests within their node module owner - keep the client decoder dependency limited to the test classpath - require the relocated CI tests and aggregate their coverage session - prevent Python caches from entering source formatting checks --- .github/workflows/check-dependencies.yml | 1 + .github/workflows/pd-store-ci.yml | 10 ++++++++++ hugegraph-store/hg-store-node/pom.xml | 6 ++++++ .../store/business/StoredRowIngressTest.java | 0 .../2f827d6e8/LegacyRowFixtureWriter.java.txt | 0 .../LegacyServerIndexQueryProbe.java.txt | 0 .../LegacyStoreIndexBuilderProbe.java.txt | 0 .../LegacyStoreIndexFixtureWriter.java.txt | 0 .../compatibility/2f827d6e8/README.md | 0 .../2f827d6e8/core-rows.properties | 0 .../index-builder-contract.properties | 0 .../2f827d6e8/store-index-rows.properties | 0 hugegraph-store/hg-store-test/pom.xml | 7 ------- .../apache/hugegraph/util/StringEncoding.java | 18 ++++++++++++++++++ 14 files changed, 35 insertions(+), 7 deletions(-) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/README.md (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/core-rows.properties (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/index-builder-contract.properties (100%) rename hugegraph-store/{hg-store-test/src/main => hg-store-node/src/test}/resources/compatibility/2f827d6e8/store-index-rows.properties (100%) diff --git a/.github/workflows/check-dependencies.yml b/.github/workflows/check-dependencies.yml index fcc234be7e..db2ec66aa0 100644 --- a/.github/workflows/check-dependencies.yml +++ b/.github/workflows/check-dependencies.yml @@ -14,6 +14,7 @@ jobs: env: USE_STAGE: 'false' # Whether to include the stage repository. SCRIPT_DEPENDENCY: install-dist/scripts/dependency + PYTHONDONTWRITEBYTECODE: '1' # Keep generated Python caches out of source style checks. steps: - name: Checkout source uses: actions/checkout@v7 diff --git a/.github/workflows/pd-store-ci.yml b/.github/workflows/pd-store-ci.yml index 1a001a03bb..ccca9d878b 100644 --- a/.github/workflows/pd-store-ci.yml +++ b/.github/workflows/pd-store-ci.yml @@ -388,6 +388,13 @@ jobs: $TRAVIS_DIR/start-pd.sh $TRAVIS_DIR/start-store.sh + - name: Run historical Store ingress tests + run: | + mvn test -pl hugegraph-store/hg-store-node -am \ + -Dtest=StoredRowIngressTest -Dsurefire.failIfNoSpecifiedTests=false \ + -Djacoco.sessionId=store-node-test \ + -Djacoco.destFile="$PWD/hugegraph-store/hg-store-test/target/store-node-test.exec" + - name: Run common test run: | mvn test -pl hugegraph-store/hg-store-test -am \ @@ -431,6 +438,8 @@ jobs: "$TEST_REPORT_DIR/TEST-org.apache.hugegraph.store.raftcore.RaftSuiteTest.xml" \ --require-test-report \ "$TEST_REPORT_DIR/TEST-org.apache.hugegraph.store.core.CoreSuiteTest.xml" \ + --require-test-report \ + "hugegraph-store/hg-store-node/target/surefire-reports/TEST-org.apache.hugegraph.store.business.StoredRowIngressTest.xml" \ --require-covered-group hg-store-common \ --require-covered-group hg-store-client \ --require-covered-group hg-store-rocksdb \ @@ -440,6 +449,7 @@ jobs: --require-session store-rocksdb-test \ --require-session store-raftcore-test \ --require-session store-core-test \ + --require-session store-node-test \ "$REPORT_FILE" \ hg-store-grpc hg-store-common hg-store-client hg-store-rocksdb hg-store-core diff --git a/hugegraph-store/hg-store-node/pom.xml b/hugegraph-store/hg-store-node/pom.xml index 9412c34107..a551aeb68e 100644 --- a/hugegraph-store/hg-store-node/pom.xml +++ b/hugegraph-store/hg-store-node/pom.xml @@ -148,6 +148,12 @@ log4j-jul 2.17.2 + + org.apache.hugegraph + hg-store-client + ${revision} + test + diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java b/hugegraph-store/hg-store-node/src/test/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java similarity index 100% rename from hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java rename to hugegraph-store/hg-store-node/src/test/java/org/apache/hugegraph/store/business/StoredRowIngressTest.java diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyRowFixtureWriter.java.txt diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyServerIndexQueryProbe.java.txt diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexBuilderProbe.java.txt diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/LegacyStoreIndexFixtureWriter.java.txt diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/README.md b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/README.md similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/README.md rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/README.md diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/core-rows.properties similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/core-rows.properties rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/core-rows.properties diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/index-builder-contract.properties b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/index-builder-contract.properties similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/index-builder-contract.properties rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/index-builder-contract.properties diff --git a/hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties b/hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/store-index-rows.properties similarity index 100% rename from hugegraph-store/hg-store-test/src/main/resources/compatibility/2f827d6e8/store-index-rows.properties rename to hugegraph-store/hg-store-node/src/test/resources/compatibility/2f827d6e8/store-index-rows.properties diff --git a/hugegraph-store/hg-store-test/pom.xml b/hugegraph-store/hg-store-test/pom.xml index 34e57864e0..2e2e50c161 100644 --- a/hugegraph-store/hg-store-test/pom.xml +++ b/hugegraph-store/hg-store-test/pom.xml @@ -205,12 +205,6 @@ - - org.apache.hugegraph - hg-store-node - ${revision} - compile - @@ -259,7 +253,6 @@ **/BatchGraphIsolationTest.java **/GraphIDManagerTest.java **/SchemaDriverTest.java - **/StoredRowIngressTest.java diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java index f046b3ac0b..fd987a76df 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/StringEncoding.java @@ -1,3 +1,21 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ // Copyright 2017 JanusGraph Authors // // Licensed under the Apache License, Version 2.0 (the "License"); From da8381d142e55740f4760703d1b3dbc3f5501df4 Mon Sep 17 00:00:00 2001 From: imbajin Date: Fri, 2 Oct 2026 23:35:09 +0800 Subject: [PATCH 03/11] fix: restore build and stable string ID ordering - restore the canonical exception import after merging master - compare string IDs consistently across lazy representations - cover Unicode ordering contracts and document the correction --- docs/shared-foundation-migration.md | 5 ++ .../org/apache/hugegraph/id/IdGenerator.java | 6 +- .../hugegraph/id/StringIdComparisonTest.java | 89 +++++++++++++++++++ 3 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 hugegraph-struct/src/test/java/org/apache/hugegraph/id/StringIdComparisonTest.java diff --git a/docs/shared-foundation-migration.md b/docs/shared-foundation-migration.md index 3ce77f1951..29131f1202 100644 --- a/docs/shared-foundation-migration.md +++ b/docs/shared-foundation-migration.md @@ -70,6 +70,11 @@ and indexes. Update implementations and call sites, then recompile every affecte integration against the matching 1.8.0 artifacts; import changes alone do not make old compiled clients binary-compatible. +String IDs use Java's UTF-16 string order consistently, including IDs loaded +from UTF-8 bytes. Decoding an ID lazily no longer changes its comparison result; +this fixes the inherited Core comparator's inconsistent ordering for supplementary +Unicode characters. Persisted ID bytes are unchanged. + External implementations of `org.apache.hugegraph.HugeGraph` must change their `sameAs` override parameter from `HugeGraph` to `org.apache.hugegraph.HugeGraphSupplier`. Shared schema and queries receive this diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java index a56eb0e236..8eb746e400 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/id/IdGenerator.java @@ -189,11 +189,7 @@ public int compareTo(Id other) { if (cmp != 0) { return cmp; } - if (this.id != null) { - return this.id.compareTo(other.asString()); - } else { - return Bytes.compare(this.bytes, other.asBytes()); - } + return this.asString().compareTo(other.asString()); } @Override diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/id/StringIdComparisonTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/id/StringIdComparisonTest.java new file mode 100644 index 0000000000..7a22f22434 --- /dev/null +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/id/StringIdComparisonTest.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hugegraph.id; + +import org.apache.hugegraph.util.StringEncoding; +import org.junit.Assert; +import org.junit.Test; + +public class StringIdComparisonTest { + + @Test + public void testUtf16OrderAcrossRepresentations() { + String[] values = {"a", "aa", "北京", "\uD7FF", "\uD800\uDC00", "\uE000", "\uFFFF"}; + for (String left : values) { + for (String right : values) { + int expected = Integer.signum(left.compareTo(right)); + for (boolean leftBytes : new boolean[]{false, true}) { + for (boolean rightBytes : new boolean[]{false, true}) { + // Fresh IDs keep both directions independent of lazy decoding. + int forward = compare(left, leftBytes, right, rightBytes); + int reverse = compare(right, rightBytes, left, leftBytes); + Assert.assertEquals(expected, forward); + Assert.assertEquals(-forward, reverse); + } + } + } + } + } + + @Test + public void testOrderDoesNotChangeAfterLazyConversion() { + Id supplementary = newId("\uD800\uDC00", true); + Id privateUse = newId("\uE000", true); + int before = Integer.signum(supplementary.compareTo(privateUse)); + Assert.assertEquals(-1, before); + + supplementary.asString(); + Assert.assertEquals(before, Integer.signum(supplementary.compareTo(privateUse))); + privateUse.asString(); + Assert.assertEquals(before, Integer.signum(supplementary.compareTo(privateUse))); + supplementary.asBytes(); + privateUse.asBytes(); + Assert.assertEquals(before, Integer.signum(supplementary.compareTo(privateUse))); + Assert.assertEquals(-before, Integer.signum(privateUse.compareTo(supplementary))); + } + + @Test + public void testMixedUnicodeOrderIsTransitive() { + String beforeSurrogates = "\uD7FF"; + String supplementary = "\uD800\uDC00"; + String privateUse = "\uE000"; + for (boolean firstBytes : new boolean[]{false, true}) { + for (boolean secondBytes : new boolean[]{false, true}) { + for (boolean thirdBytes : new boolean[]{false, true}) { + Assert.assertTrue(compare(beforeSurrogates, firstBytes, + supplementary, secondBytes) < 0); + Assert.assertTrue(compare(supplementary, secondBytes, + privateUse, thirdBytes) < 0); + Assert.assertTrue(compare(beforeSurrogates, firstBytes, + privateUse, thirdBytes) < 0); + } + } + } + } + + private static int compare(String left, boolean leftBytes, String right, boolean rightBytes) { + return Integer.signum(newId(left, leftBytes).compareTo(newId(right, rightBytes))); + } + + private static Id newId(String value, boolean bytes) { + return bytes ? IdGenerator.of(StringEncoding.encode(value), Id.IdType.STRING) : + IdGenerator.of(value); + } +} From 72c729fe11863db6106f65ba1079fa9f8b2aa11c Mon Sep 17 00:00:00 2001 From: imbajin Date: Fri, 2 Oct 2026 23:48:04 +0800 Subject: [PATCH 04/11] fix: preserve streamed Kryo reads and CI logs - consume class descriptors once across input refills - cover frozen legacy and canonical streamed payloads - retain Docker build output alongside image IDs --- .../org/apache/hugegraph/util/KryoUtil.java | 130 ++++++++++++++++ .../LegacyKryoCompatibilityTest.java | 146 ++++++++++++++++++ 2 files changed, 276 insertions(+) diff --git a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java index 02e6b7a2d3..0be4c6641b 100644 --- a/hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java +++ b/hugegraph-struct/src/main/java/org/apache/hugegraph/util/KryoUtil.java @@ -19,15 +19,23 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.Array; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import org.apache.hugegraph.exception.BackendException; +import org.apache.hugegraph.query.Condition.RelationType; import org.apache.tinkerpop.shaded.kryo.Kryo; +import org.apache.tinkerpop.shaded.kryo.KryoException; +import org.apache.tinkerpop.shaded.kryo.Registration; import org.apache.tinkerpop.shaded.kryo.Serializer; import org.apache.tinkerpop.shaded.kryo.io.Input; import org.apache.tinkerpop.shaded.kryo.io.Output; import org.apache.tinkerpop.shaded.kryo.util.DefaultClassResolver; +import org.apache.tinkerpop.shaded.kryo.util.IntMap; import org.apache.tinkerpop.shaded.kryo.util.MapReferenceResolver; +import org.apache.tinkerpop.shaded.kryo.util.ObjectMap; public final class KryoUtil { @@ -83,6 +91,60 @@ public static T fromKryoWithType(byte[] value) { /** Resolve relocated names only when Kryo decodes a class descriptor. */ private static class LegacyClassResolver extends DefaultClassResolver { + private static final String LEGACY_RELATION = + "org.apache.hugegraph.backend.query.Condition$RelationType"; + private final Map legacyRelations = new HashMap<>(); + + @Override + protected Registration readName(Input input) { + // Kryo shaded by Gremlin 3.5.1 names contain a varint ID and, on first use, a string. + // Consume once: streamed Input may refill, making position rewind unsafe. + int nameId = input.readVarInt(true); + if (this.nameIdToClass == null) { + this.nameIdToClass = new IntMap<>(); + } + Class type = this.nameIdToClass.get(nameId); + String name = null; + if (type == null) { + name = input.readString(); + type = this.getTypeByName(name); + if (type == null) { + try { + type = Class.forName(name, false, this.kryo.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new KryoException("Unable to find class: " + name, e); + } + if (this.nameToClass == null) { + this.nameToClass = new ObjectMap<>(); + } + this.nameToClass.put(name, type); + } + this.nameIdToClass.put(nameId, type); + } + Registration registration = this.kryo.getRegistration(type); + Registration legacy = this.legacyRelations.get(nameId); + if (legacy == null && name != null) { + Serializer serializer = null; + if (LEGACY_RELATION.equals(name)) { + serializer = new LegacyRelationSerializer(); + } else if (name.startsWith("[") && name.endsWith("L" + LEGACY_RELATION + ";")) { + serializer = new LegacyRelationArraySerializer(registration.getType()); + } + if (serializer != null) { + // Never register this globally: canonical descriptors use other ordinals. + legacy = new Registration(registration.getType(), serializer, NAME); + this.legacyRelations.put(nameId, legacy); + } + } + return legacy != null ? legacy : registration; + } + + @Override + public void reset() { + super.reset(); + this.legacyRelations.clear(); + } + @Override protected Class getTypeByName(String name) { Class type = LegacyClassNames.lookup(name); @@ -90,6 +152,74 @@ protected Class getTypeByName(String name) { } } + /** The frozen core enum order differs from the existing shared enum order. */ + private static class LegacyRelationSerializer extends Serializer { + + private static final RelationType[] VALUES = { + RelationType.EQ, RelationType.GT, RelationType.GTE, RelationType.LT, + RelationType.LTE, RelationType.NEQ, RelationType.IN, RelationType.NOT_IN, + RelationType.PREFIX, RelationType.TEXT_CONTAINS, RelationType.TEXT_CONTAINS_ANY, + RelationType.CONTAINS, RelationType.CONTAINS_VALUE, RelationType.CONTAINS_KEY, + RelationType.SCAN + }; + + private LegacyRelationSerializer() { + this.setAcceptsNull(true); + this.setImmutable(true); + } + + @Override + public RelationType read(Kryo kryo, Input input, Class type) { + int ordinal = input.readVarInt(true); + if (ordinal == 0) { + return null; + } + if (ordinal < 0 || ordinal > VALUES.length) { + throw new KryoException("Invalid legacy relation ordinal: " + ordinal); + } + return VALUES[ordinal - 1]; + } + + @Override + public void write(Kryo kryo, Output output, RelationType value) { + kryo.getSerializer(RelationType.class).write(kryo, output, value); + } + } + + /** Typed enum arrays omit element descriptors, so retain the enclosing descriptor's codec. */ + private static class LegacyRelationArraySerializer extends Serializer { + + private final Serializer componentSerializer; + + private LegacyRelationArraySerializer(Class type) { + this.setAcceptsNull(true); + Class component = type.getComponentType(); + this.componentSerializer = component == RelationType.class ? new LegacyRelationSerializer() : + new LegacyRelationArraySerializer(component); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Object[] read(Kryo kryo, Input input, Class type) { + int length = input.readVarInt(true); + if (length == 0) { + return null; + } + Class component = type.getComponentType(); + Object[] values = (Object[]) Array.newInstance(component, length - 1); + kryo.reference(values); + for (int i = 0; i < values.length; i++) { + values[i] = kryo.readObjectOrNull(input, component, (Serializer) this.componentSerializer); + } + return values; + } + + @Override + public void write(Kryo kryo, Output output, Object[] values) { + kryo.getSerializer(values.getClass()).write(kryo, output, values); + } + } + private static void registerSerializers(Kryo kryo) { kryo.addDefaultSerializer(UUID.class, new Serializer() { diff --git a/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java index a63fe4e78d..b9b56b44c8 100644 --- a/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java +++ b/hugegraph-struct/src/test/java/org/apache/hugegraph/compatibility/LegacyKryoCompatibilityTest.java @@ -17,6 +17,7 @@ package org.apache.hugegraph.compatibility; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Array; @@ -60,7 +61,10 @@ import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.KryoUtil; import org.apache.hugegraph.util.LegacyClassNames; +import org.apache.tinkerpop.shaded.kryo.Kryo; import org.apache.tinkerpop.shaded.kryo.KryoException; +import org.apache.tinkerpop.shaded.kryo.io.Input; +import org.apache.tinkerpop.shaded.kryo.io.Output; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -235,6 +239,148 @@ public void testOriginalUnsupportedInstancesKeepConstructorPolicy() { } } + @Test + public void testEveryLegacyRelationOrdinal() throws IOException { + Properties relations = this.relationFixtures(); + String[] names = relations.getProperty("legacy.names").split(","); + Assert.assertEquals(15, names.length); + for (String name : names) { + Condition.RelationType expected = Condition.RelationType.valueOf(name); + Assert.assertEquals(name, expected, readRelationFixture(relations, "enum." + name)); + } + } + + @Test + public void testLegacyRelationDescriptorsInContainersAndArrays() throws IOException { + Properties relations = this.relationFixtures(); + Condition.RelationType[] expected = Arrays.stream(relations.getProperty("legacy.names").split(",")) + .map(Condition.RelationType::valueOf) + .toArray(Condition.RelationType[]::new); + Assert.assertArrayEquals(expected, (Object[]) readRelationFixture(relations, "array")); + Object matrix = readRelationFixture(relations, "matrix"); + Assert.assertEquals(Condition.RelationType[][].class, matrix.getClass()); + Assert.assertArrayEquals(new Object[]{expected, null, new Condition.RelationType[0]}, (Object[]) matrix); + Map nested = (Map) readRelationFixture(relations, "nested"); + Assert.assertEquals(Arrays.asList(expected), nested.get("values")); + Assert.assertArrayEquals(expected, (Object[]) nested.get("array")); + Assert.assertEquals(Condition.RelationType.SCAN, nested.get("last")); + } + + @Test + public void testInterleavedLegacyAndCanonicalRelationDescriptors() throws IOException { + List values = (List) readRelationFixture(this.relationFixtures(), "interleaved"); + assertInterleavedRelations(values); + List written = (List) roundTrip(values); + Assert.assertEquals(values.subList(0, 4), written.subList(0, 4)); + Assert.assertArrayEquals((Object[]) values.get(4), (Object[]) written.get(4)); + Assert.assertArrayEquals((Object[]) values.get(5), (Object[]) written.get(5)); + Assert.assertSame(written.get(4), written.get(6)); + Assert.assertSame(written.get(5), written.get(7)); + } + + @Test + public void testCanonicalRelationWriterRetainsDefaultOrdinals() { + for (Condition.RelationType relation : Condition.RelationType.values()) { + Assert.assertEquals(relation, roundTrip(relation)); + Output output = new Output(128); + new Kryo().writeClassAndObject(output, relation); + Assert.assertArrayEquals(output.toBytes(), KryoUtil.toKryoWithType(relation)); + } + Condition.RelationType[] values = Condition.RelationType.values(); + Assert.assertArrayEquals(values, (Object[]) roundTrip(values)); + } + + @Test + public void testCanonicalRelationsWithStreamedInput() { + for (int bufferSize : new int[]{2, 7, 16}) { + for (Condition.RelationType relation : Condition.RelationType.values()) { + for (Object value : readStreamedTwice(KryoUtil.toKryoWithType(relation), bufferSize)) { + Assert.assertEquals(relation, value); + } + } + Condition.RelationType[] relations = {Condition.RelationType.TEXT_PREFIX, null, + Condition.RelationType.TEXT_REGEX}; + for (Object value : readStreamedTwice(KryoUtil.toKryoWithType(relations), bufferSize)) { + Assert.assertArrayEquals(relations, (Object[]) value); + } + } + } + + @Test + public void testLegacyRelationsWithStreamedInput() throws IOException { + Properties relations = this.relationFixtures(); + Condition.RelationType[] expected = Arrays.stream(relations.getProperty("legacy.names").split(",")) + .map(Condition.RelationType::valueOf) + .toArray(Condition.RelationType[]::new); + for (int bufferSize : new int[]{2, 7, 16}) { + for (Condition.RelationType relation : expected) { + byte[] bytes = Bytes.fromHex(relations.getProperty("enum." + relation + ".hex")); + for (Object value : readStreamedTwice(bytes, bufferSize)) { + Assert.assertEquals(relation, value); + } + } + for (Object value : readStreamedTwice(Bytes.fromHex(relations.getProperty("array.hex")), bufferSize)) { + Assert.assertArrayEquals(expected, (Object[]) value); + } + for (Object value : readStreamedTwice(Bytes.fromHex(relations.getProperty("matrix.hex")), bufferSize)) { + Assert.assertArrayEquals(new Object[]{expected, null, new Condition.RelationType[0]}, (Object[]) value); + } + byte[] interleaved = Bytes.fromHex(relations.getProperty("interleaved.hex")); + for (Object value : readStreamedTwice(interleaved, bufferSize)) { + assertInterleavedRelations((List) value); + } + } + } + + private static Object[] readStreamedTwice(byte[] payload, int bufferSize) { + // Start a descriptor at the last buffered byte and cross refills; the second + // top-level object also verifies reset of descriptor and reference caches. + int prefix = bufferSize - 1; + byte[] bytes = new byte[prefix + 2 * payload.length + 1]; + System.arraycopy(payload, 0, bytes, prefix, payload.length); + System.arraycopy(payload, 0, bytes, prefix + payload.length, payload.length); + bytes[bytes.length - 1] = 93; + try (Input input = new Input(new ByteArrayInputStream(bytes), bufferSize)) { + for (int i = 0; i < prefix; i++) { + Assert.assertEquals(0, input.readByte()); + } + Object[] values = {KryoUtil.kryo().readClassAndObject(input), KryoUtil.kryo().readClassAndObject(input)}; + Assert.assertEquals(93, input.readByte()); + return values; + } finally { + KryoUtil.kryo().reset(); + } + } + + private static void assertInterleavedRelations(List values) { + Assert.assertEquals(Condition.RelationType.SCAN, values.get(0)); + Assert.assertEquals(Condition.RelationType.TEXT_PREFIX, values.get(1)); + Assert.assertEquals(Condition.RelationType.TEXT_CONTAINS, values.get(2)); + Assert.assertEquals(Condition.RelationType.TEXT_REGEX, values.get(3)); + Assert.assertArrayEquals(new Condition.RelationType[]{Condition.RelationType.SCAN, null, + Condition.RelationType.TEXT_CONTAINS}, + (Object[]) values.get(4)); + Assert.assertArrayEquals(new Condition.RelationType[]{Condition.RelationType.TEXT_PREFIX, null, + Condition.RelationType.TEXT_REGEX}, + (Object[]) values.get(5)); + Assert.assertSame(values.get(4), values.get(6)); + Assert.assertSame(values.get(5), values.get(7)); + } + + private Properties relationFixtures() throws IOException { + Properties relations = new Properties(); + try (InputStream input = this.getClass().getResourceAsStream( + "/compatibility/2f827d6e8/core-relation-ordinals.properties")) { + Assert.assertNotNull(input); + relations.load(input); + } + return relations; + } + + private static Object readRelationFixture(Properties relations, String name) { + return KryoUtil.fromKryoWithType(Bytes.fromHex(relations.getProperty(name + ".hex"))); + } + private void assertValue(String name, Object expected) { Object decoded = this.read(name); Assert.assertEquals(expected, decoded); From b46c518e310e01fbb4d5ddb183fc302809638661 Mon Sep 17 00:00:00 2001 From: imbajin Date: Sat, 3 Oct 2026 00:02:55 +0800 Subject: [PATCH 05/11] fix(struct): retain shared dependency versions - exclude the older Gremlin configuration dependency - retain the baseline language utilities without PD coupling - align the generated inventory and release notices --- hugegraph-struct/pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hugegraph-struct/pom.xml b/hugegraph-struct/pom.xml index 101814b143..7b8d53bb56 100644 --- a/hugegraph-struct/pom.xml +++ b/hugegraph-struct/pom.xml @@ -40,6 +40,12 @@ org.apache.tinkerpop gremlin-core ${tinkerpop.version} + + + org.apache.commons + commons-configuration2 + + @@ -83,6 +89,12 @@ guava ${guava.version} + + + org.apache.commons + commons-lang3 + 3.18.0 + org.apache.tinkerpop gremlin-shaded From e15ea1d0b3e20e88da8291428e433fe2be261cca Mon Sep 17 00:00:00 2001 From: imbajin Date: Sat, 3 Oct 2026 00:22:44 +0800 Subject: [PATCH 06/11] fix(pd): retain the text interpolation version - declare commons-text 1.10.0 directly for PD service - avoid inheriting version 1.9 through configuration - retain core-free service, distribution and test graphs --- hugegraph-pd/hg-pd-service/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hugegraph-pd/hg-pd-service/pom.xml b/hugegraph-pd/hg-pd-service/pom.xml index 34a00e00e0..18f03dff2e 100644 --- a/hugegraph-pd/hg-pd-service/pom.xml +++ b/hugegraph-pd/hg-pd-service/pom.xml @@ -57,6 +57,13 @@ ${revision} + + + org.apache.commons + commons-text + 1.10.0 + + io.jsonwebtoken jjwt-api From ae6cdaf2387a1b748b508f31a3eef5d244c1aec3 Mon Sep 17 00:00:00 2001 From: imbajin Date: Mon, 5 Oct 2026 02:07:09 +0800 Subject: [PATCH 07/11] fix(cluster): align test node startup settings - Pass generated PD peers and the Store namespace to Server REST settings - Allocate and configure a distinct Gremlin endpoint for each Server - Detect completed startup independently of the JVM log locale --- .../conf/rest-server.properties.template | 1 + .../ct/config/GremlinServerConfig.java | 14 ++++---- .../hugegraph/ct/node/ServerNodeWrapper.java | 2 +- .../ct/config/GremlinServerConfigTest.java | 33 +++++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/hugegraph-cluster-test/hugegraph-clustertest-dist/src/assembly/static/conf/rest-server.properties.template b/hugegraph-cluster-test/hugegraph-clustertest-dist/src/assembly/static/conf/rest-server.properties.template index a16f69fe36..f838fd2a8a 100644 --- a/hugegraph-cluster-test/hugegraph-clustertest-dist/src/assembly/static/conf/rest-server.properties.template +++ b/hugegraph-cluster-test/hugegraph-clustertest-dist/src/assembly/static/conf/rest-server.properties.template @@ -39,6 +39,7 @@ arthas.disabled_commands=jad auth.authenticator=org.apache.hugegraph.auth.StandardAuthenticator # true if using hstore mode usePD=true +cluster=hg pd.peers=$PD_PEERS_LIST$ # default password diff --git a/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/config/GremlinServerConfig.java b/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/config/GremlinServerConfig.java index eeba926cab..64950f83e3 100644 --- a/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/config/GremlinServerConfig.java +++ b/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/config/GremlinServerConfig.java @@ -36,29 +36,29 @@ private GremlinServerConfig() { } public static void update(Path configPath, String host, int port) { - if (port < 0 || port > 65535) { + if (port <= 0 || port > 65535) { throw new IllegalArgumentException("Invalid Gremlin port: " + port); } try { List lines = Files.readAllLines(configPath, StandardCharsets.UTF_8); - boolean hostUpdated = false; - boolean portUpdated = false; + int hostSettings = 0; + int portSettings = 0; for (int i = 0; i < lines.size(); i++) { String line = lines.get(i); if (HOST_SETTING.matcher(line).matches()) { lines.set(i, "host: " + host); - hostUpdated = true; + hostSettings++; } else if (PORT_SETTING.matcher(line).matches()) { lines.set(i, "port: " + port); - portUpdated = true; + portSettings++; } } - if (!hostUpdated || !portUpdated) { + if (hostSettings != 1 || portSettings != 1) { throw new IllegalStateException( - "Missing host or port setting in " + configPath); + "Expected one top-level host and port in " + configPath); } Files.write(configPath, lines, StandardCharsets.UTF_8); } catch (IOException e) { diff --git a/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/node/ServerNodeWrapper.java b/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/node/ServerNodeWrapper.java index 332615b8e2..bc093cb801 100644 --- a/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/node/ServerNodeWrapper.java +++ b/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/main/java/org/apache/hugegraph/ct/node/ServerNodeWrapper.java @@ -82,7 +82,7 @@ public ServerNodeWrapper(int clusterIndex, int index, int restPort, LOCALHOST, this.gremlinPort); } this.fileNames = new ArrayList<>(List.of(EMPTY_SAMPLE_GROOVY_FILE, EXAMPLE_GROOVY_FILE)); - this.startLine = "INFO: [HttpServer] Started."; + this.startLine = "Channel started at port "; createNodeDir(Paths.get(SERVER_PACKAGE_PATH), getNodePath()); createLogDir(); } diff --git a/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/test/java/org/apache/hugegraph/ct/config/GremlinServerConfigTest.java b/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/test/java/org/apache/hugegraph/ct/config/GremlinServerConfigTest.java index ae051b4d0a..ef3ffd6538 100644 --- a/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/test/java/org/apache/hugegraph/ct/config/GremlinServerConfigTest.java +++ b/hugegraph-cluster-test/hugegraph-clustertest-minicluster/src/test/java/org/apache/hugegraph/ct/config/GremlinServerConfigTest.java @@ -49,4 +49,37 @@ public void testUpdateCommentedHostAndPort() throws Exception { Assert.assertTrue(updated.toString(), updated.contains("port: 12345")); Assert.assertFalse(updated.toString(), updated.contains("port: 8182")); } + + @Test + public void testRejectInvalidPortsWithoutChangingConfig() throws Exception { + File config = temporaryFolder.newFile("invalid-port.yaml"); + String content = "host: 127.0.0.1\nport: 8182\n"; + Files.writeString(config.toPath(), content, StandardCharsets.UTF_8); + + for (int port : new int[]{-1, 0, 65536}) { + Assert.assertThrows(IllegalArgumentException.class, () -> { + GremlinServerConfig.update(config.toPath(), "127.0.0.1", port); + }); + Assert.assertEquals(content, Files.readString(config.toPath(), + StandardCharsets.UTF_8)); + } + } + + @Test + public void testRequireOneTopLevelHostAndPort() throws Exception { + File config = temporaryFolder.newFile("ambiguous-endpoint.yaml"); + for (String content : new String[]{ + "host: 127.0.0.1\n", + "port: 8182\n", + "host: 127.0.0.1\n#host: 0.0.0.0\nport: 8182\n", + "host: 127.0.0.1\nport: 8182\n#port: 8183\n"}) { + Files.writeString(config.toPath(), content, StandardCharsets.UTF_8); + Assert.assertThrows(IllegalStateException.class, () -> { + GremlinServerConfig.update(config.toPath(), "127.0.0.1", 12345); + }); + Assert.assertEquals(content, Files.readString(config.toPath(), + StandardCharsets.UTF_8)); + } + } + } From 3a770232b5eda440f97de01e4c6857908683a9f2 Mon Sep 17 00:00:00 2001 From: imbajin Date: Mon, 5 Oct 2026 02:18:36 +0800 Subject: [PATCH 08/11] docs: illustrate shared foundation migration - Explain shared ownership with a before-and-after diagram - Lead with developer impact and concrete Java migration examples - Add an upgrade illustration and retain compatibility reference tables --- docs/images/shared-foundation/migration.png | Bin 0 -> 1291328 bytes docs/images/shared-foundation/ownership.png | Bin 0 -> 1281776 bytes docs/shared-foundation-migration.md | 438 +++++++++----------- 3 files changed, 199 insertions(+), 239 deletions(-) create mode 100644 docs/images/shared-foundation/migration.png create mode 100644 docs/images/shared-foundation/ownership.png diff --git a/docs/images/shared-foundation/migration.png b/docs/images/shared-foundation/migration.png new file mode 100644 index 0000000000000000000000000000000000000000..7de3a61d0bfa09170ce9ae9ec4a65cab8178c76b GIT binary patch literal 1291328 zcmeFa30PC-+Ah2@5E2LyP$5Xw6^zgdhLr>Yw6VreEvY!Q&QeTF0-^yGsFGcaVNxjA zB3OZ7%Z{Vp%hM#(H=&9^~e(JH@oO{WW_pVSf@rpQe z++<~V9yc}1vytA`;}P2zsSC zD|2Q3@WuKp^9Jpjf+-OU&CvLm{E475vMiP<5jkse%n>xk%E_A&u`)k@?Y*(F8#Zi^ zZBWYAob%!+3cWeIUfv{IfRQzj)P$IDf+goFfIk%((~ z98Eq?N|Muxc%>{cF^-N)jF%}BlW2vKktq@t$#E*VEFm$GRxm1=Dp5|yDH3H$6)jIn zlqDv`(@OkQBq+TfCn=Q4$^?~6p_J3|#5h@!B9T_cDKRZAPrzlo3agOIWbEs^K5<h_8;(ZH~lTpZ=WKgWh zJ4sUV(4+~&Yq+&0Tzl7u(Xpi@McnWn;*y8d zScDkQD^evrB;p~F$1!s6=Lzx2N@bEPE>1zmL$V3jq%r|}PE^tHak!Qz&~Z$hEM9@( zlnNP>kdz#!#7U_V=y-(^??Lh^oQML;fykBQq*VARC(9#0OpXkhTKL zNPsRS$YqJjgj6LCOBDx=Qz~Up6f7eSKe24Qr;LXbAaJ zOJ^xmUO7VmNitQEGFhRDmnj$s5C;Vp2tmgW?F4GC@>;qI)x`0iJib!ASdWL zq!>?LViY)STtj?v1qSn;iZWG+`wZLyk$#dgAz4A}90uz>Tovvok;5j}5El{OpVtYp zgrvlUN-Pp$OI1KA85N`u4=sS(QK(cnZ6&VdvUvE1TbokG;d!#y;Y})G@r*oS;m~H~ z!#|aff_FFMT*>a@k`+vn3}=A_#6iulAVr)k5gR1>kVMWA+NmJtjRhqoB`s9O!!#8$66Xt3Xj2qCBW;-lc2py;x^#` zG0ea08e;GoUHp(bCM)2K6UglG7#41nD61SU#k;x$oHB%xM6O|DkT6ycn@hqq9H@#c zUWwb-3{)6@uvjPq4*Ab(n3xhyeCY9E&Bo(!REhDbg>g_Ud0bNRtr!poM~3i$&EX6c z3YZYiet5G5>Ka##xXg!hzqPoW||hdl`~Veg(X9x=g` zVF|zw#S=e7hK6OZLG7!J`7M-A^x+%Ab!m<5q59tJN* zkWoS=avTNuJV^-+!0zJV591*-IYa!G5)K8c_9{{$90n`_n&Xu{{8t>tNr21|n4sZU z?X7DZWnx0YLRbZMm6RHXYZd&PQiXXE5|ZPfaVl7Z(rZ!V{h@6sVKGYLc>cU54lQZn z(01d8e=3&F8rl#R?A@O{Ii9E_5wAiH6U6Dk0Vm3d3Swd+FL*#4kymc;h_DQpI&s9q z_lY1#@Qs7zzzcd!Hc3vdVJbw$u^@&xH0Z37L}$zkXO$X9w1)r-oH~>%4hD(Qr3}SKsU{c09UNZy&VA#0Xl=x3;$&66@S9IaZ`=E z^Z!2QC0@GYx0zwDyo`ZzjCgrp=J3NM&t(k#%i_g^#$2-@-)u5%SZU626pVw1RZW&N zlbN{r^2B@ParYt|CnY5^2$_kBrP+CFGV(VVa?R5+%{lq|OgV;Zb7t~NL;izv=Vz`r z=jH*7W@WC;pX|ku>r7dhS@{ObBWoVZHJayJ*P07v4C6oJdRf-me4`ft=9o9+8P}N1 zd9lOK=Xsyc$MdoIxrVG9vuTtnu<1Di&%dl^F3pqnuSd)Xf{}(oq2;Zk# zdh6u^z+iyl4cLBewjp=5*(7@`XT_Swa{dEhK>OlVaq&xY4HnC^p##w67%h*P%%)#) z3@3+=P4hoKwv~pwl`@kd-|*+DRh?<_VT+xnFOL0|zijLjE%A9M+Uz58$D<@;kbKad5i07;|=SyL0ZlR_CoX8y5~KvKby%#%w^2BEtarP*`732) z$mO|t8L)eJ=B&J|%p61hW4Y#nS+}jjJ8|s)qoi+Wt$z-eJ8YQC|JqH-|M&YH8gbHX zEC06={L9Y_%dzE;rC;4RM!nN~pK;2(v)_rH=~|`Pc;k=4hnClLuHf%Y85;MV|7hGl z4PkiLiX*?~9{KEJz=|8>ikNR@!tHbe2Y2D>tJMS zb24w!c8Z$*?y%I^CTspv!cg||Nhk_*0&Kij;4Ua}^4^{rdJx7`}a1d*rwgnsjLAIn%n!-L4=qnKcF(_iSHJdJ)J zYdw@}O^$pFBjyP(-R4UHECDOT-)PX}lXql>EO|6@4|#(lj2IdwSuuASolI<#eguk{ zm6J(hsJr3Sf0p7h0hdUVyqC;_|GbefCUj_tqG2PPvo?8644s;q zEFa5+4^2Dj-`OX#gc-^6^$Lj18kQ7?<;&4h+=pI%z~ysuN9&xarz~OL{+)X$f%qhwa~CNYvYrNFU-6?Y0ck@SxcE> z)ldlcrQ=EO}rAH-tONZ^NUNU(6r* z?j}!Q!n&nrw$v_>_cB8A@kkcyCYQ}n%m{K7NUpdXHqS9M`b081&o7$C;<8GzZM09!)}F9=MP-#=Nz% zTPMmy|M>`e^Y~kj7!7|u;B^y|al@FK&nS6q@w;8GIaw5w!Io1u-9;qPP93 zUJ87H`{}~$$=_#&e|)TB(ZyYp4*EXv_@o_6=RLcx{NnRYyz-h&wL0_L2OjW!=G7in z>Dxao>-v1`lFEWDoOefoj6pWlnk^{BF>c9cOAcrsiFY+Jj8PQ*6?Gs(Zr6M>hDDEG-zIOi+`Oa5TnL-jz~DPbI6?mQNkj?WM9*mvM`WMS*@x1PI>_jej%)iX~ zcFVtIog6MRbI1ogz-Vu?`gB;m;?Gx!50Ekuw_akiLPBnt^euyrHLf+T&HGRB6uD5z zTb|;!h;_@dKlZ;dDdjCw276(e_~6H5U#egE#IbJ&kG}b~CjY)yPh1Y0VyvHhpwicT zx#;}Ms~-A36PEo$R{Tf3r?Os}{eE*y$UPr@wddftt1oHJytQ-7Mf=EC?2{XQjq};Q z;w}H8Z+{9nTJ`Jef6qj;ou8Ml*qfD~mp^~aYBON$UgLU$Wyz=~nc`8K{|s!t>^;S! zHsDqso5hj`G66h+esc=T%;BG33cxl0MEr((-?Ki%UOc zj1qsHyK%#=ZQnnTp*#A#{crbO+dFdL_gU+y8ugd=^s@OX_G|mOXEr=14k4M3oMDgv z%i};mFi1iZ6PGd^8;ix}Kj6Acr*Or5w5M2_Em=d8Fwq5tlIhz@5u2R z`mfoRsq2oAg$ys3<&Wh*{?FcO7%%XJ?Br?k5M~tdCceUeM+`aij9ftIEaXG-|4H~2 z!WVjR0%!gs)8q(3L+)twa4^PAT9=pi*iiHz4*MV|K^UqOD&l|=m;|_=p-bkm|IEda z5bE`nfwwI#)og$iS^I7m6Hb{^%zB!_{U_PQtRm|Bv!`C$e*Nd`QM=zMc+tQ;dvnA+ zhDlfVmiH{*zprlBh>Fi(Dq6eaupdN%wc z{@V-tP0MZ^{pzV*18jQl-6!Kee^He1UBo59th#4kFU@nvHoi3X!Mpdo{&Uv&pPRPa z^S3280!NLC*Iwz%dN}kUI^ma<-GPIXj}-5q!)FGKm=T;d<+)LtkItN)k+^U6tf;fk zy!n{0d-j%9yYo-dqkUM?F<{p`{8J11I2D@*1*S6}+rw%qy!H+#QMUUBHBtjwrsZKt08 zWtDGqiSFC;lf`i(-b(U4nECeW&x||GKK%Cd%${6U`S#@tX7XZQJNVP{ze*2o;M`yG zq-oyM+p2^~J7zXbIq(O!VekFoswqDo3svov{bqcF&0$fjzZWp;{{yT<&UfrYf}Mz3 z-hxQ{+r0I2QS*!UJ!yM<%BjsgQ`h#jmo&^P_$L7O%c!55-U*#QWkPbSpT_|K;PR=xBm^U+((xW>w*+ z^D}z4xpy8N_f6c4n}!bxE_`CB>uPlxK zdRgqf_s{k-e8S91ZoD~L)+uSd|K1onY!UO=s;5jd_q`{0KjhOrnUT}7GcR-2u0J|4 za^aP2kx?gS>X>4mLU_K6Vb90i%01h8%Ky}7VNGp=vxA;_{`pa$;6Ky3gagZZ zolEd-&Se;gF|;?^`OEEz0~KPn zVwwKrX#J5(2V&Fr#m_EFEX&#*x9h!Gy~$I0;*%`V$KV7>l zK6dfh&?Eadyn69SVt4CDlaw9n13%FOZRoo3&ZD7|H6MOasdk7z(Ttkb(6xPP%oEh= zhp*Ys&OIV{aQf);J`)!FacIt(`Ss8I`ox=;SDuf!>u=|t+?HH9x8FqL?6S25FMqL6?Q`WL+rDpKJNWz6{eMsE zTKUQY{mh16I^yzIFUaoPa`hL5+P-eY^pTf-oEv!c#wT2PbkX0ChB^yoiK?K2(e z8{VJt&NBOG=i}G6Zy#XIUnC0O;0l#zzb>7-cJT1HnO|(3^ZT~2bIZ&A7<9k?>Dd=AyuSN)Nx?lu zKYzV;@dlP?^KVV{@My}d*a!{f!eUx|OzE655Bu)2UK6YKeAByXHY|lLK#vJM&C-bknW^c*e z{Oiy2SX;*N-~Q;0=y(fHRP)?@t5@xM^Sa|c-<|8*g&&KPHt9b5di!1X&*iWBG}TpM z*mdy-=c$vLoV9;Tga>xR1HU`$fk)20&r(tKvy`KZdHT|vr>;Ix{A2jPsLlT|9yosK zzj)yIrT>L%D`rRBE+{YhWCsF$vi;b^(0;G^?t@WpzGgo^=GDjcFAVQ}`B3w!n&msJ zzttQWHCcN3xMR#g{jn3z_E?`iXLe&0&p$smui3Bt${0_FF1Fz9 z4}NSLnEGqu`(pxs*<;ujQ!(-EJYG=fm5HLAA9Tk4TG25rc*Kp!aUW*K_x$))yk4`v zY~HcoFI3kLPU_wDH__@5I=O3fe?m4wN;>448t?c-OwXmQ)KW=J)ZOJ2jPca;H$n_t+;w)!~XQfw9h}6SEoK@ zz8O-~HSOKI<&T^dC%>D*&3WPzQ%LhYqHkW8-FsyI(%glMJo{HYG47(jpVv~4ygK3S;xhWs#bZB>-MfLhaPJJ|KKqXczvIa>Ue8!_xT1DX;WHxw zCGSqVoc{Au-}SUQK2|>E%nmD@+LxM87fa$&zsHFUv-&V?>;T+xG36cI4re z?*{~p2|M28_-u~;?F;w3{L_}L>(cJ7+FJhiiKC3udws4wZg|=-n4JOh`-F;s=)vN)1W-Qorc!+#m6a z{rIxfn64rBpTU^^jr(W)GhYbS;4iZA-#YUDH=cg+<)UrE`d=)D8>csq{bX6`*cU!I zcJzfug^%jGj_$puXY#J2i?94#S}{d^dCkYG#=kyk--4Q-Gm9G1-z3+JVzP*PYzkBuh5m|MY z*<#_{q4!1IJn)>ze#zXm=hyFB-`@W21Frf*ekm(2EO<%sy#DDMXFqx3{l_=cJ4bl- z7rfW`nMQWH$j3iz#r{brt}Yx9TYaAjI{4#1`afKIV@9`eziCkY-NENgZRy9$_>;#q zz58|RhtCCl`tVz8D>v`DDm(7?`v(i6CupOS(|+7rY?$g?_fylQy6?W}YFA%-b;FUC zbM%SS?b8*YDQS=P!vF+?br|G+QJ@aIF9|I$(4wa2`++y7*m*0cAwD3f(vmEThP_0}uXt-fo=onOUyBVor=i?2^VK7V3W z31>=RU!-!vdy6-`a8zE*SqV>X0?EM?)&7?<2<%b+BaY)Xie^tSYa%n|PufGkkq7(} zWy8e&^%++l!KJsJ{rP$OvnfYcYPS6twr{Wi4LBh!OriLQZp4eh-yOiFQ8Po8<7h87=4mUqJ;^pqgzbj$n&n*AN`Q@4iPxwX5Q=C8eOWVu! z{F!M92j-s^42}GUsCUgcs(n9+3q*nSRWnyhi+p zvsRWbfBUoh52TM+-kbW;!qM!hPcEDOV}c~*w9j|5f{VZTV^jJQr~WvexIM=(@1EfJ z_RFpbcZGB>{%G#8$#*Z!YkZG;Z&3P#G2fU1w94WMv+i{s;YV-Sx$4L7|M={|K*K*8 zK7FoG(z5BH`^1Hd9XX)_ zpVuGO_$R;c&b-BSC!Q5PuxsUl>hN>(j(uti-c!50ZRIzU{Km}WzIY>buK3gO7wrU>;*;p-ku# zJ%Ym?<3n*r-JiPgsk#1JEP11k9n7iwUUXqQeTMsQYgzxk2xirH5Hm43sYLHyY;3`Zv!RL|}`ed|oCQpVVMwm)7j#ta&6VZqtPutqmFCz7Xqx>~hP4!i(FoLN5NW zko8OAheanMg|lKe|2~`NILZh|Ke8n81y*VvD_K}HJ?8I4TbQEK+c3|+vw(l%_x^3U z=6_Ow^|hgZOjyN#N~i@Wtdnx5*9v{OZ1C!TDL03+l48tkCg?$lweHoQcBEXYJy!Nu zeasi-zkZTCyJ+gqm+m?@{+_AJC(^6=6;rSG_D>tDG@4%e1VxSK!bcm{7cBU^IkD`G zxL5bj`XZ*$xAm$lXU~fXb#wPHZ#}b`I{fMrjbo!WpO_UeV*cBtTV~0`vA4Qq?)4N#OUz8f~jBEIxB^Zqz$% zqk^km3y)~OKO@-xGvR$R(hPg#2XwW;GxYQ7ul+-yH&5n&b@#_JTbrLA`_cDf_a%hq zzBcQ8ZWwPtG&M54SogrR`30<>9GpGUB|AC?Z*I7-^>p`(xigIivin4*Fwq@&V(tg_^5#IG-+RIm2#&}T`T8Tm$I;Sv-dgjxz9GPP3oY^2lS1Z3Vdp% zE2B$W+g(Y$EC~yMJ$n4 zJ=Lo`z3$}^kb#8?XPi<>%1Yr0S7mAH2Od0)Uqt}rbNf_xjCT8ZH9w5gsioMSyST7+ zjm@eWOl`4-NKB0bbM%hI<)IqBMjcDc(&k7rEDLrHrBqW7M<9W* zd4jc_^_f8mcM>_nwsNj}iG>4gYhejpWg=~__r6gBT`cdicy^YGY}q#^)-X0mov#t+ zHHcyr#_r~n!#$pfjB|QT_JyblUxoKm7S2FkK9E6m*+jABqIPv7%y}Yna~v^mE0m#uW;)f4A~t30_K&K-4Esjb56rB|wom8xxtDNl)?-j6d!5LJ$ChjP4pl7Fv#BSq zro)V7Z!o)FL&TMA>*K*rC64;g2l#_KtK`nz z4yseDhGb|6gXYpz@<1sxD~8Kw*-ka{v6ANA8Bnt!ixzt{HB^ju!8cdVH~YG ziX*1hO@+i+)kjm)3=VhMNG%40f;#IQ*ZfOkpt4@;Y-!zHEsq_eOUn@HDI?{%tD~7; zT|nne^;ld>xcbIT71^*|2W_7YqlOo%DWD`2!xwd?MOJoI;Rv876g)K~0|zLp<L>XaR_AS}=@e-r`6m8e($E6Sl3{f84 zojnffc~wWLh%!2LHFEco(yA+q6d^8aMW(_zGg#j^Ai?RjQSfb@*chd+vYzLUWpMF{mqYahZxZd5& zA8Zrath7;*es_P1Jhm#xRajG6FuM~0*?Cf2-2u1gSHkM{NIE>y(i3W5PcdKTDq|pH zk@FO}OgX%@$0LGRyYtAvlZEcq-j=Pc+LZDEiNJH0(48di_DnpZa+k?rIedpcUF>mElUZ$REseiPpB)i`_-|YRPyX`hyI3{tZoThdw-|8@`T=AcSx!`H|KP3{nfrs zy}d_oZ?w|=L=+~A{S?m=gJV0o`-Hk$YComNA}B1MTy-lO1~M3NH%G_DT{sv!^co+L zA&f-6o>=8g1xL@+59rfrk4CFihkEYnZVv0eb~UW~dPiPRplR?NmtCZxMST3O9L#%y z(o&r*BHNWvKK8H(A;#atfge%1zjX2k53X>u976D%5gbTYc3JvW?&T(i*i65AIqY9* zY7A``_ak}=Sp3p#tV!0ap={O>yb9l%j^_GJ4b~BzEpq1y2780|0Q`W6nzveW*z3xw zvps6Aja5}v5Hf)hhPWF#IDCPJT^?O(F=Ab5hHk`O?4VYoa4+e&E<=-B*Caj2EJaIq{8D-c&)gJdmy!07jH(6pO@CS#y9Mzw^JeU<6_ZP)L1rm31}& z0D&~)oEGd{VK0GutrXRTb(mdN5@kq)X0=!gE&eRN#CSlYZLz+O;18F32#`?|Y?JdW z6DmSy1iM?so)|6Pv$Ki|GY#R;rIbUQSB9`7a`~+*%f2y|fTT8Bds?LruZDq82!dKZ z17F9NT!?}{>!f&^YtdqgmEy7z_=;sAt^$Rnl7R1&vh>}=!1^fwPO65%5`y7w>iVD= zUf_W@+Rr)N#5JWu75WKGs>nRVlEVAI!wyIV9!)2KSWf)9FIrG#P2WKkk?4=$msbM; z7UDd#{3WnNEYPe?lN@LYpkS|*u~bC$@}w+nT1FMCY9b4hi#5UC*utevRdReJHcBui z2kvzUCjq3_3_;kVsqOCNks5YC#ly}Zxq*otqp^)NNyQM70(8|OLRQOZ%$MT2668{J zVWvi3ECQ}2Bv2nd7!yqQUz;gq@hk)@0eRGgHNi0uiL}G}PD_(8fqMI?dc5NwQEK53 z|DQ&b*jfaK=UdIy+e@awiP}Vq_ylwd;iY*M(SXVP!8G7dR<}|>d15;G5{!*AWjY~2 z0@!8B9j8VI^H^@5kuE<3@*>0xK*n~e+&9?eXK3^lu^U5)!U7}_ykx9GsL@g_t?e}B z;8h>hp0=^zlG&pAO%*IJ?0}N#;7<_`2u@bmtVKe$=Cms*jMEaNwUzed1+l}CtWa!@ zmY z3z?XTEB0&@NDcrz0d3F*&s_xVYS_k9DukB7F}SWUyefDTd+gv{r7V$aIelX~TWC9l z7}PL89}u~Gf?{`C??=FCTkF0OEaudQZj+L5oZVkT_GZ)Yy*7AbG9V1kVk90nn7D7a z{3$~5poJ}Ps1sQFDi+owq(#oi8_6lycRJrl?7dSR%AxHgRMpnjZm|U3889y5#%LJU zG>b<~00@+^ySY5nk(QBH7Qm;tdPJUa4oFxkMV=@IB+{@4H}<&;J7I-&4Ojcr)ujbF zypjT1r>@oj2mk`O`nvri?6ubO(!Q3S>&OczHWLCkS0goGHR?v- zQfz{%_f@$4N-i%t6p*52L$3ghs<}LM^gt@ADF{lb;fgtY z2Vyl-AKjfNzckW`c(01B=ju5wMdJW%4+Ls0l1dIB-9=)=*J+VqT#F_VZ!rbHsc!7? zpQxh+gK0t=7BOhiYDsENR6E2t&LO6%vN>W0{O1aIDuPYvbyJH><1}KCcE8!L$V&CI zkrOHF!l=QBpu@=WjMW8^fPyX7*)TbMIC77Ikik?Q#le5?M&j95&9(K64z_u7F&lY| zE-5%q!VThZh(J`g1ThWFL^hxe0hLnF2}q>{*e*j1yIyLKV#H!Xvt`Ed5? zC;`=lfJoI3NVtoEepzhejft*?m?AkvQ!En2VTz?yz(AmE+HI{`HgcbAdm|-qxcvm6 zdHO==bqxW4DO`S2fZjfN+5G?(a%FC!U_ok>fu^q@MGUZ4KZRT!{08V(~V2rjr zx(Z?@r`zYgBJZRScGoo=-CYoA6cQjtYuZ(S2*}f}_MLNL5b6v~D3=tZ-_EC{-DV!^ zG!LF6b=aSIK7h|JV=ZM zObbChW_C4^wigdMpGMLdX`imYkV(KnAKVNOX{ORS6S+CXp($h4A*trH7>chY9*gR< zP2-EmIrtv7(iOfUdYpzgXyIv)2f^{PU?npFh#I>hMC=Qy_B+8 z-~viOask8Jq+A*w68~dA)0Sd!ARp=WR2LjWs`WmSRIUv>DD`nC^`=Fh0V3QAIwy+gw*4uzt77*@HYTCS8m(7&zI9;3Xa0r=&&op;}5C47Ub<=vq?MgG{zrm*N6@ z!s)#hoq}|x8kST9(>=O-t2I(GnCePu2t7;b!zoMnOxKlQWK#5viR_Xf+X;QTXx&s` z;SjK>JgUe-!rjqSwh7)ouWTz4F&b_}9PY1E$CgwV7+^dWc-zb%u|w>+2IUf$O4CIp zt*Nvq&?E)UqVz^jjEaW^otwip8X*)8?Z5%1^CjtwC$*D=bI2%=g?o(y6M?vFu3$=(zOg&hZgA#iW1a7ahs^BeyoF~;b%{gZqgP>R6C8a!V-Tr1UBN|(iHKe3K z<=H5v$RBtEEg5hz@-I{4rU0W6DzAm9z`2WBwpv+2`a)*+bzvvv29yCZv$z%Eobt?V zTp9qYw%{1aVP^qU6PWI9u-I#v-uleu4zt^D-P8#pHq&b(@zj1wT?u^=Ay2`WQi&xT zIrEY#7F8k-2?hgQgD|jB?A1IFRmk2nYN%vbn1&KF7#twXIn8zg7vOw?DIREYwXIY- zXlX&t%@XL`t@WV}vCzHz9X88#!YUBp!QuBJ z%wGpNKy`3PVth@&qU~GcV3(awTO)yr^&Fl#GEk3Sb6}HN92Beu8B}Y%?_r0#&uef- zdk-xGN#0pQ36|+EL>c^HG9At0CPcKG!QlcC#S^;vz^bwOX^0L^)K7P9HJ@;N99^%C zMGzh>0I`WM=x+u%fcu3P;SH*>s&qb3Fkcg5qcnP8s&Nk0qVg`OU3VJd6tRKmx$w9Y zVH|^1&ROcHL8{%>lP9Vlc*oY-jpNV}#Eh`C+Zws9j6wpVo~i|$6gYSm;>PqdK^#w9 z*MIJsvoRoM=-3+-nh+ z2adB~T#dy6MhWQ|Y96sj7O8&94KNRgEmgnMf;F>L&f{$6#IgeU;+ zBEFbVu@PuaE8JED;Jm|=S+0hT=7vl~Ie5e+@S(`W07Nt`+d4cXou^qY1qd~&{;JM~ zh1eWqi*Rj(n+2>S03KBYc9V6l7g0^EX<|WVG<*s2-oaF?-MNBj6j%j{(R*UORhx7k zj_wQ~K$w?z4+C=#2pOwWSGMl%@t7;=0<=&G}5?t2_A+SY4$(2uQP5mm+O`_mVJ#r0LUJ3Hp=89;cyP+!EKC3*my+x`+$VDA* zkr=Lw!iV7OKz#anC<1G82t8OAK=C*=P_lJXIrUxL%09J?rJ)Ja2qw)2cmlVO&h&%B zQn?Fx926*HgW>UkBmu-E{i>VnqH57%x|)T6jUY^cXTzXJcU#{t9{^!yn1KDY^D8og z`N*+J46-0+)caF|ZD3NSgBjmeuoo#PxYH`Die;M?Tz*x+b+zJeR2Y!GdNjeosz5!} zIAA7K)=~$1&=QPUv^EOdX&vQZi~R?$0f;n%ZFcl7PJxp}<_Mq0mJr@r9V-wZ=8J5H z4}k_`qiZ&=O)236)LM zDIU~lN&P7XU;`BrAtBY+7Wgbu_ce8UCV;jwRBoV3VE0MT*f~`26;BX|6g&pC(5|X0bz!I!irQ5-BUSAwCY}xF@tKU23arRLhJfc5OehsN#AOgH|76B1? zWti8QOaXVHbSNz)H38%<&2U;^ zY_T2_vJr+HU~O=EHOOv|{7N-!Q&lUhn{YLMmQ1nFU@c0F(5#Z9T2eLS!Z=x!tH`Sc z#A72G%_XT_peMDxJ`-^Xn=X$A59yguN&%L7(?q5BsM|@EozyCQYSCl>wh)OE;h3_OK6M!#$!@M0m@ZYOOj|(vqIK~@;aEAUaFHVirtW)W@~r8^qXOdW{&Qj`P~mQETWKk^t_(2>c1H0$`{2S{sNeu3 zk$}baXj5v)@uB)qc9=!lLhO|VGF6=bWiw8^pV(=*I!Mm%{4oLC!APf%YGIMWh#p#bg>mi><4N%ub$XZ2NUf{2Vj!Z*I<6%S?aHFyMSKx*VTrCL8{T~2LF5{aP9E1) z$VSm*aayDlM|ZS61*TL0z=Q@75qsU#ys0JDX{Dk?uxEH`cF`gDw+m4u#{-B^#W#># z8J%st>9Me7DoWEzhihiyV-$+EE)LJ`fds_#5xvJVZoa z)@d=+%UjJy9Sy8;59ux-&;gnU8c5VtK^GMGLTpSl29%Nk-6!XCF zlG;QKdW-N0k}@3|jV)W`aLLyyAsi5N+bDr|a#Rwgql5x3h_uF}pth-!XwY9rXiyX7 z*@*=11f&Py5IGP$lb(nie6jujaq)OB2??=u@F2EEoV6_*)2HCbOe8Oyh=V1iNAesC zO*K+97@+Ru)r&>FYOvl$s)@zrGkWxz!N1^?i!3sw4O-MinumNw*6D1}IDjY8utZw! zkQi5aGh-Dn9|{I|fYPA1tc^yhrjOxh`9%RX3ZP^e_&qOnAv7=57>&XT=}XIi|Hov| zMSWxFX-FT9E}qn2Yy#aC1vDaC)x<$q_i_>_W|GdJG{Xeo+?i~^hIdHCHHaWQG+v;Q zqY$vBHlUug=AgQTD)~4l37`q#xEFidCRSj*-b5CKR!Y*PuAGK;0$DRFuVHJ4CsP!N zU5AmfGyDd@08u&{isH5#-gg$St2WeHi5LN0B6MPe_@?t_fTrE1hjejB2UfJ5+ ziJXpcLa!*X5O{SSme|ijg5gQ)_Rp{ggUj(BN5@t_L| zfD9uMgkB9L%^9kkfCwvT%7zU4cYrm~rbU)oRVCBVf+H0mBLY2U!~Q+&Fp6b^p9>_t zjRcaFhobCALI^m)u5N#n-p{I>$th6dfr)k$Imom?NCn%#jon|0V?;+&AOI*@V6KBF zH+q>f_PT~@ctEM><~(Svk#U~Hxm^{o2;(@;(WydVuO%D(9^GcJu9Pa44R8thir9nK z#Dp&i0efIQ1}BO{2yWOuzR?$c3z>lB#`O+=6ot`Kp>R%XqdWNoD1fzVUyLS|((2O7 zp*l7sPgy8Z!fDJ@E<)QxcH=-qM_w(MTZ5gD!qwGiU;&rnKXLG)mp;j8%-qI+X1J>B z1zM$gRX6?M)C*J)n}h`tHx;F59qGi;ieZ8X38^*N>68v1)JSz{62R{c)blElfAmqo zs43&FH!Pqa2&T4(3 zjpgkogGkY47FGqH=DCJkpam2)WJVy!Ho3E|Ra+i<7KIMN93rV__3Ob)3*FYR4h}L@ zilm>j;RRDrsfWI!KPVWTA|W_?%GeKyOGp8^`}*9B2!m%I8V06;uI1VSYA6nRHM`*G zkX84$%|(wx$RIn6)efl2hJQhlfo8!BP6{BA&W0OK6H2J0-;(Hpw>1GhmIO1@qP7Cu zQHiqsP}?z@)Cf(FD5GUJjpy3ClIw1(z8j849$}-c25)jTd5{+OnpbLV8<}mv@rJD%353cpJ_qJYqU}%B*RpBQVoij$aTQw0mY&%1)UlyH1@Qx8ly>n zIPfAuEwJJ7vTW&K>fy>|k zkj?vsacmS-WXv+tvcwRRe6092cdmG;Y^U&c!;Pq(qvveWDa~B~`EROD|e1J`H^!@b% zkr$%uvua4EG>1P}O!^MFuCi)!Hl4g`;9Cj!OWDZS?VwzDqVzz48;cF9LGx}AaAzl~ z?4g>P>g;i+cXV*dLsLjrQH#tGv|4nSkS*Z46@&YN;3S(4fk||@r|z=S;Y9_Mf8JD- z%n=@u=_P~Ikr2oPHy)@*Vug0WgrWk_qCj0p9d3I2`_4IA4taf+{S;y;4&t1X*I_31 z4EskF*;bI_o=(0X(2`9FsOsv1Ao5r?a1V?q3d6HmVggc;l|`Uy?$Bgi@THM1t6&JL zp&1rT8Nu72134`{{$6+^8DtZ0iWF9_q0s8tCc-q{-YlF-09%6^k)<(o8^N|LB~1UYhD%U8ho z+=`-tNOYNOMOH~#;81D4kSV&k4!zXjU;&FLN9PWyy`+E=2*SIMR}@4RS&J;5;yx7! zBT)^o&>*`1fFfB{Tai^6fei*$Py)1Uu`KCvgxAtHz`6?IV)0drYUGEPMxrgsqPzA= z3LtKTvaSzwStH_3q%N3XiXbGJ)6vY0!;c9@z4k&>y0{44ATDc|1t=SSy;y94B1PPI z4a*Qn0L=-eYefQ8(@_a?M_(=ID%aGV8aiF9D<61AU5yFQhKlA|5e-6GLmR-qINUzS zAJ|k8w-X(p=#OnLSr$vF_TE&gCYp`GX=Kvb2D1XQP*a7^}DVt_qZ7JR-x z9Po)5sJQDLZiPRvsf03I$b`RHRF1wijrKJ3sux^kHXJ)hj20G>HuxOUvH(GN>9s6?KbbFWw10_Qgs&W1+06nPj7 z0?UPO#>ayiQjT@ZK+-8jV&y<3j*Yrk0R^DXgJ8f;Hj)lU(hP|*mpT*$M=o{`bg_=RQgLKlXD|<%6h-wLwNvG$dAE*~C z!DSTdFv?~_+d%t(h)$fHp^#VT|>A5%&-8+RlfcXP}mjG(PE~Z&H8e4%3 zHjTctsw;CONGJexRc=4l;cWC5qk$tmm>-Vsw$P%wKGg8_OdXQ26eQ#pf`G1Dj3hS0 zW%qb$s++9ydV67y*%aCZNFO-bJ~x(w)$TZ6jJUG{B@m<`h}J4_WM~d6@9H>?u-F5y z>L5h~RBM&UrBQ={z8u6}; zs`E%NJcjPkZXXiLVo_AB*yO_k3n^$q4FlxdxYPB%0ODfLzC!`M?k`ab?Dmi3qJU#3Q&)(2dsspC+NGt7aXLXb6DUNp;O7%0^kr4?6lr~cb-LP+nSA%Pv(%F z*s?w7=87$!#t-xC!*^`3euDf^%R;P2W`YtP4zGoDzM+#0jg^G3U}^9Tu0HkhPC!?X zEcl1J6$LaYQYHi~BnB2w8flXOEjZOEk$^80qOGw;R1SKRe1i-A96$qSi&9c0yyJgk z>V4p$ss$RvRAd-jx-IQ~`z--&sBSi1QK?i6YqK^`Y_ri0+jUL9l(tG$_8vfuZ& zN7v>L!sYYlea?CPJIf*-1{9V5qJZ!Z&&+*ob^4;?SAiW*U8@aKi0;N#&<^+zoN$M8 zMV)o0h55GhiyL^CfeBQO^sVg<`E}qO{b=z2iwMx(pez%iCpUrty(`9jR@+u@}Q$ z%gbppe-G^t1RPiv4U3~s;DgKJB;L?Wt9@@6wZ)ljpm?AK=(?^yj_YRhMb4r8lsk*>Zd+pfnF#lG5>2Vp*9IH0YtS&>haTd>a*5lj&>!%r;s6`EEq=Cfk_m9lLuJ= zx49u3VKs7=yJ<#a!}D_Z#-0cS1-CIR-rph8EXb5SMZ1IF?+^#E(_;a2EXVt_-3MXD z9pX?xif0F3V{~|LpMLXj*z)m0?%fGl=tX`4aCU?TI~-@QEmZ@`7wVch{S{a;Q4jd( z#%)CJn>6(dsYQ|eW|d(k;1A%h45K4tudRKZRDeDZ4(y2s94Jh2xNpK<%?_o-00~;9j)3 zbnrFSbYZ8<3QSuLoP+4m!i5MtDdl}` zy$)nK`XZCB`afS`yV-H+A|1z3eJH#h@k%=md?d_RvScAR`s5DP^ zGo$!`5p1a<+S+OEC2t5J5a9wY?zj+zwU@7qdb2}=CBskk+#hj__kl9g%il!C(BHV0 zN`{mR2quN%a0MXLsBGX{8m;ki1{_}QwMP*LXpFB0I|e7%y{EFKb0syA*L&{wH3mqA z)b|We-y5WvNrby(qfJUSRt%XZ7SDI`tua@7~+Dy_Vj2hucP4t(+P~RqY2(^ zh5kJTu=CxtkQ=%1z?)^r6Zr0Vd1*sY=pPUS1R;AyPUC9Rn1wnVhy+z|ELLfuAI!Cy z8nT@LRH1nXKgr_9HaAwq@)8Nq%kE35tJWU1Vq(+~5l+r7^{9X#GYT*q-uWzVJTF;F zUJv5)j)uz8p{dy{v=g-R@P1xTLN9}}Tc9srmq>`^vuS|W6*^Gd6(8-tmKvp**x{nl zQq>DcHpUd)TxT&pg87~up}E-U#WIWDPY~O%096K0q^EJ01GG=FziK3_{1z7gY&-ag zHrhwL2XH^}#;1x3+Ztc_gI8BF1!U9!dUHo;d)rYyVD62XwpV%!S##EHzSGL{gXQ^9 z4kqbu!LjKLN7oO6)&!IT1^uX_y7EJuA2-(<(Hb<*XaRSqI0u~uZ*avRB5+6$3~ao| z=qRy>z>4k}ftovsssyXd7>b5aVZ1#Un)hNJb_WpsOB^*+8V}}$GAL8?TjaBah@xA$ z*9{I0vVx1=*s%o9IplJg?A9Ovj)$(v0u>hQ6`^{M6(0p(cZH)2b1M=6|9rR%8Z!p1 zxG}q191Y^Q>G#b^3M=W%O_f{)2_f@^tk0W-RjESJ%<;p?HQ<+#Hy^Z?=4z#l5eJ0` z=98L{nOchjfzF0j=#FZga7f5Y1Djy()XhnUnoVuP@oz5T3ZBN@<2- z{1z7Yo!^DNSt4q@<-E86cl_)`U6P5}SP^)0s^@-Bqzj*glS1zq6d)k;rI}Od9*W%( zbA~gEL{}K>Qs$U&d=vW6`fkK>UW{Yc?sZf0Vm1RVRfMy~+_(^i8F^45ToY>4GT>7z zWDF-<90B(XcLKUBL+~i=%8&jhi7R1!=)bj2>^&N zlR2<0(?K(rWDQR;>f1~8uI3y3&TB&WGA z-Rph^pUFCo-Gdj35AX+%G(5)X42y`V1I8#HtgxoH3#%<3_*5NY)#{mZe1-u^`M`y+ zYV=Eh>vAX)7GXtW*jRU$q7b_32L!>SLPHg8r1)FrFSPD?_}M|W zkKfq)noe;pm6Q03*ttD0;cHmduF0cyC0#Rs4hYj`*5T8E|@%Zo4~j1J2}QI$FW zQBFGQAWh=PjMwW!{KE5u&|~lFRtZUSoY{DhF-LNzYa!lpnV;tBVq1+t&gNqBgz{Rz zm^703P}4gKJ_1axC@EIZp3VWvm2+ZZ{%NpfXZf@A*Qa{flT|^To9#gayB%+1Cz=P~> zHj9%(cpA`gWeCOJWRa%2yVT@Ys8v@v^}WTBlS}x2o9^1_ zul#`KxI$jVGTDB4^{B2*bSv14Y#;uh+*HjAwT?Pdbs5DOLz%tGPc;hJ z<6TFvK{0v3$1{NPXh*TSzZEI)?e!&2e+s~)uK82ohj&3NxlMvJ+xo|zzXS#0PuLKpl%TeU>&EQLZHU?M`MTX zw`vB51066AHDY~+8-8&^iq%U-J`0r+w5e21`GR>uxPP}(puopDM`HmDsFp{v8bnIb z9SWJ5urL)d!6VzFQI{5omth;e0pSw*(N&o~j-ykwL8;vLK|10qSafQ8D;(Gkh-xuk z$Me87yEaqXLvYjiF9842R1})9Bs0Y`jqctHx|GHzW9ZSiFN_@AnXm8-nV{|ka&s~tFjjMfGY9YBAMKa1$hL7y95@U$R|hBH^}@uUb4K6T zwz6V!$>AH{vYr4+=N2Qb3!0%cW+h?rA+vZf4%Rhupt%WNXwxCc??KMPGTek<88;sC zFH1u3(>6qBVqy2pi3Bb{6xJZ`L|2U>f@a!&s1q+4bJ|tZM)?#N5c5Mf9yy-#7K1g- zMaF~=#bqKnBw^dWol-kg@d73ZIiRQvLbqV0BBq1)Gof~X7@z+BOz?2ziF-rjMl@Q( z*B>98nmvN6?(~_HYh1iZgJZ{TZD)pnHRYF_?OW$d^R+E<*xCM&s4gr%o8cePuOt7& z1kORJ`(IDj<)j>?@Vy;Pi03aL$mV}+8`+1Dys3@3Qs{XxjvY9{sguujH$o`-t${`0 zFJVqS++ArHb2Z4Ee*v%x;=rJ2jGo3dfaY7hF*AG%4KKDVKEkuK#9_w%~| zZQ}F?HRk&;w=gq-Ohh?$F!*C1LGBd-Uu(Srgb5!5mbfDg3)hZVU*ltLQCg8x8oGyI zilML$V#%V&^)x)y*#QbPdLasTnk>%913_$F`AkbY*jd<%`;NhrBDLBPbW(D#3i%>9 z2z$;#_dCO*1;HeLZkUl0egCXnA!oN?+2b7W&!7{jTz<+5RI|lik&5 ztqKJKQsWoMi{K7-`Z66!RJh=O8;wGO`lXWvml5Zw28acnF{SM*R5Leoftw z=cL~?wWyP41F(cb4VqKyh+&&e3hT%BWJoB~gGkK4(iVPW(6TXi1eMypBFD^gNSMZO zJkg^{k8e#dhpnMXBRv2(MR6i#?SWwBhd{fz!Aoft{X9nv)-V7V0IP+p6m*Q=(}w!m z3e*VVJqk}iVbg@jOrrp)fknjpFp(LO8AwSvR)g*|;8?5*U1IIHz)&?taJiB21*T)z zeRLntOvTFyg*bw2g7QS5k`8qwYMsnQp(_j;&`fGAQX-w}1b}jd_z+0Sq@1WHhi|12 zJI48eEOsYXwJ{Sz-9aLte*=kP^66QOordB+`;GpjMe>&_!}{Dl&TZmg9_3;3)5Bu= zEr`S!`>ZAyceEJ00u;D)H1|UJ;Dh|wiO_M*m36B2(#pzOF2U<2V5{+|#)`@D*vv0+ zhVjq~E+s`tHbPC3l+J5YX9a&po$521D4CptJbtcn`BS%*UXdHrau@;*Q@tkeGzbuQ zlBAy(#s=icohg+TUA&%<>dGM6&2nD1fO%+VF^tyn>fXeK#eEMA*tnF+@EwOo_cDE-9fUkw z#!DNh{D1?*GC+KTHC0rN8e*n81RKaNqjRX|fyCw0-<^=?M~$faQB=owfF_A>$!mV;4Bn-(bJ5wl2kC)pwRxYR8iiw(<35AaZU8t@5=uT2cTFJ?Q6)O31 zkmi3!5LJK%lybW7kCSu-;7!CGJk&PCi}s4OOFa=xVT2-foEa2b`AkXcjRK3pym(?P zer9lBQz^xyuOB5K*L+g3yP?NUq(wsueoxs0nbr`3CKc%> zIp!y5$z3=cyyXtYn8y9!10Sc&EXKRP7ley5bq}Bv%`M&JQvRaBpT~9I5yXzgKZQ@j zhuxMX^UhX55oV$#TtvV~q&vma0a}C_igOgO-zaPEbu7eN8m0vjkeocAvsBa^V{X`Z z#v%k-%V5>cKg{7f(0D;KV;qj3se|)m^_1O)Kut+*qkFJVd!tT3%?f^34Jp#aWM