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..56f7210cc8 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 @@ protected List tableNames() { .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 tableNamesToTruncate() { + return this.tableNames(); + } + public String namespace() { return this.namespace; } @@ -371,7 +380,7 @@ public void truncate() { }; // Truncate tables - List tables = this.tableNames(); + List tables = this.tableNamesToTruncate(); Map> futures = new HashMap<>(tables.size()); try { @@ -383,7 +392,7 @@ public void truncate() { 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 void truncate() { 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 void truncate() { LOG.debug("Store truncated: {}", this.store); } - private void enableTables() { - for (String table : this.tableNames()) { + private void enableTables(List tables) { + for (String table : tables) { try { this.sessions.enableTable(table); } catch (Exception e) { @@ -575,6 +584,18 @@ protected List tableNames() { return tableNames; } + @Override + protected List 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 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 70aa5df7d0..7ed172acd9 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 void testWriteAndReadVersion() { 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 graphs = openGraphs("g_1", NAME48);