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 1d75c00944..7a9de48e26 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 @@ -114,6 +114,14 @@ protected List tableNames() { .collect(Collectors.toList()); } + protected List getTableNamesExcludingMeta() { + // Exclude meta table to preserve system metadata during graph clear + return this.tables.entrySet().stream() + .filter(e -> !(HugeType.META == e.getKey())) + .map(e -> e.getValue().table()) + .collect(Collectors.toList()); + } + public String namespace() { return this.namespace; } @@ -371,7 +379,7 @@ public void truncate() { }; // Truncate tables - List tables = this.tableNames(); + List tables = this.getTableNamesExcludingMeta(); Map> futures = new HashMap<>(tables.size()); try { diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CoreTestSuite.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CoreTestSuite.java index 2ff62b06ef..2797b3287c 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CoreTestSuite.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/CoreTestSuite.java @@ -24,6 +24,7 @@ import org.apache.hugegraph.meta.MetaManager; import org.apache.hugegraph.meta.PdMetaDriver; import org.apache.hugegraph.testutil.Utils; +import org.apache.hugegraph.unit.hbase.HbaseUnitTest; import org.apache.hugegraph.util.Log; import org.junit.AfterClass; import org.junit.Assert; @@ -47,7 +48,9 @@ TaskCoreTest.class, AuthTest.class, MultiGraphsTest.class, - RamTableTest.class + RamTableTest.class, + /* hbase */ + HbaseUnitTest.class, }) public class CoreTestSuite { 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 f9f20ab9e5..f0b3e13b4a 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 @@ -44,6 +44,7 @@ import org.apache.hugegraph.unit.core.SerialEnumTest; import org.apache.hugegraph.unit.core.SystemSchemaStoreTest; import org.apache.hugegraph.unit.core.TraversalUtilTest; +import org.apache.hugegraph.unit.hbase.HbaseUnitTest; import org.apache.hugegraph.unit.id.EdgeIdTest; import org.apache.hugegraph.unit.id.IdTest; import org.apache.hugegraph.unit.id.IdUtilTest; @@ -142,6 +143,7 @@ RocksDBSessionTest.class, RocksDBCountersTest.class, + /* utils */ VersionTest.class, JsonUtilTest.class, diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/BaseHbaseUnitTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/BaseHbaseUnitTest.java new file mode 100644 index 0000000000..449af964c8 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/BaseHbaseUnitTest.java @@ -0,0 +1,83 @@ +/* + * 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.hbase; + +import org.apache.commons.configuration2.Configuration; +import org.apache.hugegraph.backend.store.hbase.HbaseSessions; +import org.apache.hugegraph.backend.store.hbase.HbaseStoreProvider; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.testutil.Utils; +import org.apache.hugegraph.unit.BaseUnitTest; +import org.junit.After; +import org.junit.Before; +import org.junit.Assume; + +import java.io.IOException; + +public class BaseHbaseUnitTest extends BaseUnitTest { + + private static final String GRAPH_NAME = "test_graph"; + + protected HugeConfig config; + protected HbaseStoreProvider provider; + protected HbaseSessions sessions; + + @Before + public void setup() throws IOException { + Configuration conf = Utils.getConf(); + String backend = conf.getString("backend", "memory"); + // Only run HBase related tests when backend is hbase + Assume.assumeTrue("Skip HBase tests when backend is not hbase", + "hbase".equalsIgnoreCase(backend)); + this.config = new HugeConfig(conf); + this.provider = new HbaseStoreProvider(); + try { + this.provider.open(GRAPH_NAME); + this.provider.loadSystemStore(config).open(config); + this.provider.loadGraphStore(config).open(config); + this.provider.loadSchemaStore(config).open(config); + this.provider.init(); + this.sessions = new HbaseSessions(config, GRAPH_NAME, this.provider.loadGraphStore(config).store()); + this.sessions.open(); + } catch (Exception e) { + tearDown(); + LOG.warn("Failed to init Hbasetest ", e); + } + + } + + @After + public void tearDown() { + if (this.sessions != null) { + try { + this.sessions.close(); + } catch (Exception e) { + LOG.warn("Failed to close sessions ", e); + } + } + if (this.provider != null) { + // ensure back is clear + this.provider.truncate(); + try { + this.provider.close(); + } catch (Exception e) { + LOG.warn("Failed to close provider ", e); + } + } + } +} diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/HbaseUnitTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/HbaseUnitTest.java new file mode 100644 index 0000000000..c851016139 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/HbaseUnitTest.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.unit.hbase; + +import org.apache.hadoop.hbase.client.Result; +import org.apache.hugegraph.backend.store.BackendEntry.BackendIterator; +import org.apache.hugegraph.backend.store.BackendStore; +import org.apache.hugegraph.testutil.Assert; +import org.apache.hugegraph.backend.store.hbase.HbaseSessions; +import org.apache.hugegraph.util.StringEncoding; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; + +public class HbaseUnitTest extends BaseHbaseUnitTest { + + @Test + public void testHbaseMetaVersionAfterTruncate() { + BackendStore systemStore = this.provider.loadSystemStore(config); + + // Record system version before truncation + String beforeVersion = systemStore.storedVersion(); + + HbaseSessions.Session testsession = this.sessions.session(); + + // Insert test data + testsession.put("g_v", "f".getBytes(StandardCharsets.UTF_8), + "row_trunc_v".getBytes(StandardCharsets.UTF_8), StringEncoding.encode("q"), + StringEncoding.encode("v")); + testsession.put("g_oe", "f".getBytes(StandardCharsets.UTF_8), + "row_trunc_oe".getBytes(StandardCharsets.UTF_8), + StringEncoding.encode("q"), StringEncoding.encode("v")); + testsession.put("g_ie", "f".getBytes(StandardCharsets.UTF_8), + "row_trunc_ie".getBytes(StandardCharsets.UTF_8), + StringEncoding.encode("q"), StringEncoding.encode("v")); + testsession.commit(); + + // Verify data insertion success + try ( + BackendIterator vIterator = testsession.get("g_v", "f".getBytes( + StandardCharsets.UTF_8), "row_trunc_v".getBytes(StandardCharsets.UTF_8)); + BackendIterator oeIterator = testsession.get("g_oe", "f".getBytes( + StandardCharsets.UTF_8), "row_trunc_oe".getBytes(StandardCharsets.UTF_8)); + BackendIterator ieIterator = testsession.get("g_ie", "f".getBytes( + StandardCharsets.UTF_8), "row_trunc_ie".getBytes(StandardCharsets.UTF_8)); + ) { + Assert.assertTrue("data should exist", vIterator.hasNext()); + Assert.assertTrue("data should exist", oeIterator.hasNext()); + Assert.assertTrue("data should exist", ieIterator.hasNext()); + } + // Execute truncate operation, clears all graph data but preserves system tables + this.provider.truncate(); + + // Verify system version remains unchanged after truncation + String afterVersion = systemStore.storedVersion(); + Assert.assertNotNull("System metadata version should exist", afterVersion); + Assert.assertEquals("System metadata version should remain unchanged after truncation", + beforeVersion, afterVersion); + + // Verify data has been cleared + try ( + BackendIterator vIterator = testsession.get("g_v", "f".getBytes( + StandardCharsets.UTF_8), "row_trunc_v".getBytes(StandardCharsets.UTF_8)); + BackendIterator oeIterator = testsession.get("g_oe", "f".getBytes( + StandardCharsets.UTF_8), "row_trunc_oe".getBytes(StandardCharsets.UTF_8)); + BackendIterator ieIterator = testsession.get("g_ie", "f".getBytes( + StandardCharsets.UTF_8), "row_trunc_ie".getBytes(StandardCharsets.UTF_8)); + ) { + Assert.assertFalse("data should not exist", vIterator.hasNext()); + Assert.assertFalse("data should not exist", oeIterator.hasNext()); + Assert.assertFalse("data should not exist", ieIterator.hasNext()); + } + } +}