This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph.git


The following commit(s) were added to refs/heads/master by this push:
     new 7bb624b99 fix(server): keep the hbase meta table when clearing a graph 
(#3176)
7bb624b99 is described below

commit 7bb624b99dc12c948cd62736ae26583a05195da1
Author: KAI <[email protected]>
AuthorDate: Sun Aug 30 22:16:16 2026 +0530

    fix(server): keep the hbase meta table when clearing a graph (#3176)
    
    Clearing a graph (DELETE /graphs/{name}/clear) calls truncate() on each
    of the three stores. HbaseSystemStore.tableNames() appends the meta
    table, so the truncate also wiped the backend version that init() had
    written there, and the next start of the server failed the version
    check with "The backend store version is inconsistent" (#2209).
    > Supersedes #2911 by LYD031106
---
 .../hugegraph/backend/store/hbase/HbaseStore.java  | 31 +++++++++++---
 .../org/apache/hugegraph/core/MultiGraphsTest.java | 50 ++++++++++++++++++++++
 2 files changed, 76 insertions(+), 5 deletions(-)

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 1d75c0094..56f7210cc 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,15 @@ public abstract class HbaseStore extends 
AbstractBackendStore<HbaseSessions.Sess
                           .collect(Collectors.toList());
     }
 
+    /**
+     * The tables to truncate when the graph is cleared, all the tables of
+     * the store by default. A store that keeps backend metadata which must
+     * survive a clear excludes it here, see {@link HbaseSystemStore}.
+     */
+    protected List<String> tableNamesToTruncate() {
+        return this.tableNames();
+    }
+
     public String namespace() {
         return this.namespace;
     }
@@ -371,7 +380,7 @@ public abstract class HbaseStore extends 
AbstractBackendStore<HbaseSessions.Sess
         };
 
         // Truncate tables
-        List<String> tables = this.tableNames();
+        List<String> tables = this.tableNamesToTruncate();
         Map<String, Future<Void>> futures = new HashMap<>(tables.size());
 
         try {
@@ -383,7 +392,7 @@ public abstract class HbaseStore extends 
AbstractBackendStore<HbaseSessions.Sess
                 wait.apply(entry.getKey(), entry.getValue());
             }
         } catch (Exception e) {
-            this.enableTables();
+            this.enableTables(tables);
             throw new BackendException(
                     "Failed to disable table for '%s' store", e, this.store);
         }
@@ -397,7 +406,7 @@ public abstract class HbaseStore extends 
AbstractBackendStore<HbaseSessions.Sess
                 wait.apply(entry.getKey(), entry.getValue());
             }
         } catch (Exception e) {
-            this.enableTables();
+            this.enableTables(tables);
             throw new BackendException(
                     "Failed to truncate table for '%s' store", e, this.store);
         }
@@ -405,8 +414,8 @@ public abstract class HbaseStore extends 
AbstractBackendStore<HbaseSessions.Sess
         LOG.debug("Store truncated: {}", this.store);
     }
 
-    private void enableTables() {
-        for (String table : this.tableNames()) {
+    private void enableTables(List<String> tables) {
+        for (String table : tables) {
             try {
                 this.sessions.enableTable(table);
             } catch (Exception e) {
@@ -575,6 +584,18 @@ public abstract class HbaseStore extends 
AbstractBackendStore<HbaseSessions.Sess
             return tableNames;
         }
 
+        @Override
+        protected List<String> tableNamesToTruncate() {
+            /*
+             * Keep the meta table: it holds the backend version written by
+             * init(), truncating it makes the version check fail at the next
+             * startup (see #2209)
+             */
+            List<String> tableNames = this.tableNames();
+            tableNames.remove(this.meta.table());
+            return tableNames;
+        }
+
         @Override
         public void init() {
             super.init();
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 70aa5df7d..7ed172acd 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
@@ -71,6 +71,56 @@ public class MultiGraphsTest extends BaseCoreTest {
         destroyGraphs(graphs);
     }
 
+    @Test
+    public void testTruncateBackendKeepsVersionAndResetsSchemaIds() {
+        // hstore keeps the schema in PD meta after truncate and caches id 
ranges
+        Assume.assumeFalse("skip this test for hstore",
+                           "hstore".equals(graph().backend()));
+
+        HugeGraph graph = openGraphs("truncate_g").get(0);
+        try {
+            // Start from a clean backend in case a previous run failed midway
+            graph.clearBackend();
+            graph.initBackend();
+            graph.serverStarted(GlobalMasterInfo.master("server-truncate"));
+
+            BackendStoreInfo backendStoreInfo = graph.backendStoreInfo();
+            Assert.assertTrue(backendStoreInfo.checkVersion());
+
+            SchemaManager schema = graph.schema();
+            schema.propertyKey("name").asText().create();
+            VertexLabel person = schema.vertexLabel("person")
+                                       .properties("name")
+                                       .useAutomaticId().create();
+            graph.addVertex(T.label, "person", "name", "marko");
+            graph.tx().commit();
+            Assert.assertEquals(1L, graph.traversal().V().count().next());
+
+            graph.truncateBackend();
+
+            // The backend version written by init() survives the truncate
+            Assert.assertTrue(backendStoreInfo.exists());
+            Assert.assertTrue(backendStoreInfo.checkVersion());
+            // The schema and the data are gone
+            Assert.assertEquals(0L, graph.traversal().V().count().next());
+            Assert.assertTrue(schema.getVertexLabels().isEmpty());
+            Assert.assertTrue(schema.getPropertyKeys().isEmpty());
+            // The schema id counters are reset: the same ids are handed out
+            schema.propertyKey("name").asText().create();
+            VertexLabel person2 = schema.vertexLabel("person")
+                                        .properties("name")
+                                        .useAutomaticId().create();
+            Assert.assertEquals(person.id(), person2.id());
+            graph.addVertex(T.label, "person", "name", "marko");
+            graph.tx().commit();
+            Assert.assertEquals(1L, graph.traversal().V().count().next());
+
+            graph.clearBackend();
+        } finally {
+            destroyGraphs(ImmutableList.of(graph));
+        }
+    }
+
     @Test
     public void testCreateMultiGraphs() {
         List<HugeGraph> graphs = openGraphs("g_1", NAME48);

Reply via email to