From 155edacb2b072225a5cbd73024b23e3302ca85cd Mon Sep 17 00:00:00 2001 From: yichen88 Date: Tue, 25 May 2021 17:13:48 +0200 Subject: [PATCH] Add orphan node check Signed-off-by: yichen88 --- .../afs/cassandra/CassandraAppStorage.java | 36 +++++++++++++++++++ .../cassandra/CassandraAppStorageTest.java | 17 ++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/afs-cassandra/src/main/java/com/powsybl/afs/cassandra/CassandraAppStorage.java b/afs-cassandra/src/main/java/com/powsybl/afs/cassandra/CassandraAppStorage.java index c9ad9cbc..a8621cde 100644 --- a/afs-cassandra/src/main/java/com/powsybl/afs/cassandra/CassandraAppStorage.java +++ b/afs-cassandra/src/main/java/com/powsybl/afs/cassandra/CassandraAppStorage.java @@ -48,6 +48,8 @@ public class CassandraAppStorage extends AbstractAppStorage { public static final String REF_NOT_FOUND = "REFERENCE_NOT_FOUND"; + public static final String ORPHAN_NODE = "ORPHAN_NODE"; + private final String fileSystemName; private final Supplier contextSupplier; @@ -1504,6 +1506,9 @@ public List checkFileSystem(FileSystemCheckOptions options case REF_NOT_FOUND: checkReferenceNotFound(results, options); break; + case ORPHAN_NODE: + checkOrphanNode(results, options); + break; default: LOGGER.warn("Check {} not supported in {}", type, getClass()); } @@ -1512,6 +1517,37 @@ public List checkFileSystem(FileSystemCheckOptions options return results; } + private void checkOrphanNode(List results, FileSystemCheckOptions options) { + List statements = new ArrayList<>(); + // get all child id which parent name is null + ResultSet resultSet = getSession().execute(select(ID, CHILD_ID, NAME, CHILD_NAME).from(CHILDREN_BY_NAME_AND_CLASS)); + for (Row row : resultSet) { + if (row.getString(NAME) == null) { + UUID nodeId = row.getUUID(CHILD_ID); + String nodeName = row.getString(CHILD_NAME); + UUID fakeParentId = row.getUUID(ID); + FileSystemCheckIssue issue = new FileSystemCheckIssue().setNodeId(nodeId.toString()) + .setNodeName(nodeName) + .setType(ORPHAN_NODE) + .setDescription(nodeName + "(" + nodeId + ") is an orphan node. Its fake parent id:" + fakeParentId); + if (options.isRepair()) { + statements.add(delete().from(CHILDREN_BY_NAME_AND_CLASS) + .where(eq(ID, nodeId))); + statements.add(delete().from(CHILDREN_BY_NAME_AND_CLASS) + .where(eq(ID, fakeParentId))); + issue.setRepaired(true); + issue.setResolutionDescription("Delete row and its parent row"); + } + results.add(issue); + } + } + if (options.isRepair()) { + for (Statement statement : statements) { + getSession().execute(statement); + } + } + } + private void checkReferenceNotFound(List results, FileSystemCheckOptions options) { List statements = new ArrayList<>(); Set notFoundIds = new HashSet<>(); diff --git a/afs-cassandra/src/test/java/com/powsybl/afs/cassandra/CassandraAppStorageTest.java b/afs-cassandra/src/test/java/com/powsybl/afs/cassandra/CassandraAppStorageTest.java index b1428a93..ae27c792 100644 --- a/afs-cassandra/src/test/java/com/powsybl/afs/cassandra/CassandraAppStorageTest.java +++ b/afs-cassandra/src/test/java/com/powsybl/afs/cassandra/CassandraAppStorageTest.java @@ -26,7 +26,8 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto; import static com.powsybl.afs.cassandra.CassandraConstants.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.*; +import static org.junit.Assert.fail; import static org.junit.Assert.*; /** @@ -48,6 +49,20 @@ protected void nextDependentTests() { testSupportedChecks(); testInconsistendNodeRepair(); testAbsentChildRepair(); + testOrphanNodeRepair(); + } + + private void testOrphanNodeRepair() { + NodeInfo orphanNode = storage.createNode(UUIDs.timeBased().toString(), "orphanNodes", FOLDER_PSEUDO_CLASS, "", 0, new NodeGenericMetadata()); + assertThatThrownBy(() -> storage.getParentNode(orphanNode.getId())).isInstanceOf(NullPointerException.class); + FileSystemCheckOptions repairOption = new FileSystemCheckOptionsBuilder() + .addCheckTypes(CassandraAppStorage.ORPHAN_NODE) + .repair().build(); + List issues = storage.checkFileSystem(repairOption); + assertThat(issues).hasOnlyOneElementSatisfying(i -> assertEquals(orphanNode.getId(), i.getNodeId())); + assertThatThrownBy(() -> storage.getParentNode(orphanNode.getId())) + .isInstanceOf(CassandraAfsException.class) + .hasMessageContaining("not found"); } void testInconsistendNodeRepair() {