From fb0d48027e568104bbe7c68d4ebef1c6f880d1fe Mon Sep 17 00:00:00 2001 From: Evgeny Budilovsky Date: Thu, 16 Jan 2025 18:02:32 +0200 Subject: [PATCH] [Filestore] issue-2865: discard deleted nodes when recovering existing local filestore session --- cloud/filestore/libs/service_local/index.h | 20 +++--- .../filestore/libs/service_local/index_ut.cpp | 62 +++++++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/cloud/filestore/libs/service_local/index.h b/cloud/filestore/libs/service_local/index.h index 7a5a03048e2..b76d1efb075 100644 --- a/cloud/filestore/libs/service_local/index.h +++ b/cloud/filestore/libs/service_local/index.h @@ -309,17 +309,23 @@ class TLocalIndex // parent already resolved so we can create node and resolve // this entry - auto node = - TIndexNode::Create(**parentNodeIt, pathElemRecord->Name); - node->SetRecordIndex(pathElemIndex); + try { + auto node = + TIndexNode::Create(**parentNodeIt, pathElemRecord->Name); + node->SetRecordIndex(pathElemIndex); + Nodes.insert(node); - Nodes.insert(node); + STORAGE_TRACE( + "Resolve node end, NodeId=" << pathElemRecord->NodeId); + } catch (...) { + STORAGE_ERROR( + "Resolve node failed, NodeId=" << pathElemRecord->NodeId << + ", Exception=" << CurrentExceptionMessage()); + NodeTable->DeleteRecord(pathElemIndex); + } unresolvedPath.pop(); unresolvedRecords.erase(pathElemRecord->NodeId); - - STORAGE_TRACE( - "Resolve node end, NodeId=" << pathElemRecord->NodeId); } } } diff --git a/cloud/filestore/libs/service_local/index_ut.cpp b/cloud/filestore/libs/service_local/index_ut.cpp index ef124431ca9..efacb87279e 100644 --- a/cloud/filestore/libs/service_local/index_ut.cpp +++ b/cloud/filestore/libs/service_local/index_ut.cpp @@ -269,6 +269,68 @@ Y_UNIT_TEST_SUITE(TLocalIndex) CheckMissingNodes(pathLen, missingNodes); } + + Y_UNIT_TEST_F(ShouldDiscardDeletedNodes, TEnvironment) + { + RootPath.ForceDelete(); + RootPath.MkDir(); + + StatePath.ForceDelete(); + StatePath.MkDir(); + + auto index = std::make_unique(RootPath, StatePath, 100, Log); + auto rootNode = index->LookupNode(RootNodeId); + + // create /dir1 + auto dir1 = RootPath / "dir1"; + dir1.MkDir(); + auto node1 = TIndexNode::Create(*rootNode, dir1.GetName()); + auto inserted = + index->TryInsertNode(node1, RootNodeId, dir1.GetName()); + UNIT_ASSERT_C(inserted, "Failed to insert node: " << dir1.GetName()); + + // create /dir2/dir3/dir4 + auto dir2 = RootPath / "dir2"; + dir2.MkDir(); + auto node2 = TIndexNode::Create(*rootNode, dir2.GetName()); + inserted = + index->TryInsertNode(node2, RootNodeId, dir2.GetName()); + UNIT_ASSERT_C(inserted, "Failed to insert node: " << dir2.GetName()); + + auto dir3 = dir2 / "dir3"; + dir3.MkDir(); + auto node3 = TIndexNode::Create(*node2, dir3.GetName()); + inserted = + index->TryInsertNode(node3, node2->GetNodeId(), dir3.GetName()); + UNIT_ASSERT_C(inserted, "Failed to insert node: " << dir3.GetName()); + + auto dir4 = dir3 / "dir4"; + dir4.MkDir(); + auto node4 = TIndexNode::Create(*node3, dir4.GetName()); + inserted = + index->TryInsertNode(node4, node3->GetNodeId(), dir4.GetName()); + UNIT_ASSERT_C(inserted, "Failed to insert node: " << dir4.GetName()); + + // delete dir3 + dir3.ForceDelete(); + index = std::make_unique(RootPath, StatePath, 100, Log); + + // /dir1 and /dir2 restored + UNIT_ASSERT_C(index->LookupNode(node1->GetNodeId()), + "Failed to lookup node id: " << node1->GetNodeId() << + ", node: " << dir1.GetName()); + UNIT_ASSERT_C(index->LookupNode(node2->GetNodeId()), + "Failed to lookup node id: " << node1->GetNodeId() << + ", node: " << dir2.GetName()); + + // dir3/dir4 discarded + UNIT_ASSERT_C(!index->LookupNode(node3->GetNodeId()), + "Did not failed to lookup node id: " << node3->GetNodeId() << + ", node: " << dir3.GetName()); + UNIT_ASSERT_C(!index->LookupNode(node4->GetNodeId()), + "Did not failed to lookup node id: " << node4->GetNodeId() << + ", node: " << dir4.GetName()); + } }; } // namespace NCloud::NFileStore