[ox/fs] Fix FileStoreTemplate::compact to skip first item and correctly find parent

This commit is contained in:
Gary Talent 2019-07-19 20:14:09 -05:00
parent 31b75d1e50
commit 8fa5488d77

View File

@ -164,7 +164,7 @@ class FileStoreTemplate {
/** /**
* Finds the parent an inode by its ID. * Finds the parent an inode by its ID.
*/ */
ItemPtr findParent(ItemPtr ptr, size_t id) const; ItemPtr findParent(ItemPtr ptr, size_t id, size_t oldAddr) const;
/** /**
* Finds an inode by its ID. * Finds an inode by its ID.
@ -492,8 +492,15 @@ ValErr<typename FileStoreTemplate<size_t>::InodeId_t> FileStoreTemplate<size_t>:
template<typename size_t> template<typename size_t>
void FileStoreTemplate<size_t>::compact() { void FileStoreTemplate<size_t>::compact() {
m_buffer->compact([this](uint64_t oldAddr, ItemPtr item) { auto isFirstItem = true;
if (item.valid()) { m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) {
if (isFirstItem) {
isFirstItem = false;
return;
}
if (!item.valid()) {
return;
}
oxTrace("ox::FileStoreTemplate::compact::moveItem") oxTrace("ox::FileStoreTemplate::compact::moveItem")
<< "Moving Item:" << item->id << "Moving Item:" << item->id
<< "from" << oldAddr << "from" << oldAddr
@ -503,8 +510,9 @@ void FileStoreTemplate<size_t>::compact() {
if (fsData && oldAddr == fsData->rootNode) { if (fsData && oldAddr == fsData->rootNode) {
fsData->rootNode = item.offset(); fsData->rootNode = item.offset();
} }
auto parent = findParent(rootInode(), item); auto parent = findParent(rootInode(), item->id, oldAddr);
oxAssert(parent.valid(), "Parent inode not found."); oxAssert(parent.valid() || rootInode() == item.offset(),
"Parent inode not found for item that should have parent.");
if (parent.valid()) { if (parent.valid()) {
if (parent->left == oldAddr) { if (parent->left == oldAddr) {
parent->left = item; parent->left = item;
@ -512,7 +520,6 @@ void FileStoreTemplate<size_t>::compact() {
parent->right = item; parent->right = item;
} }
} }
}
}); });
} }
@ -668,25 +675,25 @@ Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
} }
template<typename size_t> template<typename size_t>
typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::findParent(ItemPtr item, size_t id) const { typename FileStoreTemplate<size_t>::ItemPtr FileStoreTemplate<size_t>::findParent(ItemPtr item, size_t id, size_t oldAddr) const {
// This is a little bit confusing. findParent uses the inode ID to find
// where the target ID should be, but the actual address of that item is
// currently invalid, so we check it against what is known to be the old
// address of the item to confirm that we have the right item.
if (item.valid()) { if (item.valid()) {
if (id > item->id) { if (id > item->id) {
auto right = m_buffer->ptr(item->right); if (item->right == oldAddr) {
if (right.valid()) {
if (right->id == id) {
return item; return item;
} else { } else {
return findParent(right, id); auto right = m_buffer->ptr(item->right);
} return findParent(right, id, oldAddr);
} }
} else if (id < item->id) { } else if (id < item->id) {
auto left = m_buffer->ptr(item->left); if (item->left == oldAddr) {
if (left.valid()) {
if (left->id == id) {
return item; return item;
} else { } else {
return findParent(left, id); auto left = m_buffer->ptr(item->left);
} return findParent(left, id, oldAddr);
} }
} }
} }