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..bc0f9f2b8b 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 truncatedTableNames() { + // 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.truncatedTableNames(); Map> futures = new HashMap<>(tables.size()); try { 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..c79ab79455 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/BaseHbaseUnitTest.java @@ -0,0 +1,71 @@ +/* + * 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 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(); + this.config = new HugeConfig(conf); + this.provider = new HbaseStoreProvider(); + 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(); + } + + @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){ + 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..96845b3e9d --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/hbase/HbaseUnitTest.java @@ -0,0 +1,82 @@ +/* + * 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()); + } + } +}