[ox/fs] Fix FileStoreTemplate::compact to skip first item and correctly find parent
This commit is contained in:
		@@ -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);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user