diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index 069b5dcf1..6ad970d03 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -50,8 +50,11 @@ class FileStoreTemplate: public FileStore { using ItemPtr = typename ptrarith::NodeBuffer>::ItemPtr; using Buffer = ptrarith::NodeBuffer>; + static constexpr InodeId_t ReservedInodeEnd = 100; + struct __attribute__((packed)) FileStoreData { ox::LittleEndian rootNode = 0; + ox::Random random; }; size_t m_buffSize = 0; @@ -70,6 +73,8 @@ class FileStoreTemplate: public FileStore { Error write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType = 0); + Error remove(InodeId_t id); + Error read(InodeId_t id, void *data, FsSize_t dataSize, FsSize_t *size); Error read(InodeId_t id, FsSize_t readStart, FsSize_t readSize, void *data, FsSize_t *size); @@ -91,7 +96,9 @@ class FileStoreTemplate: public FileStore { FsSize_t readSize, T *data, FsSize_t *size); - StatInfo stat(InodeId_t id); + ValErr stat(InodeId_t id); + + Error resize(std::size_t size, void *newBuff = nullptr); InodeId_t spaceNeeded(FsSize_t size); @@ -99,6 +106,8 @@ class FileStoreTemplate: public FileStore { InodeId_t available(); + ValErr generateInodeId(); + private: void compact(); @@ -116,12 +125,20 @@ class FileStoreTemplate: public FileStore { */ Error placeItem(ItemPtr root, ItemPtr item, int depth = 0); + /** + * Removes the given Item at the given ID. If it already exists, the + * existing value will be overwritten. + */ + Error unplaceItem(ItemPtr item); + /** * Removes the given Item at the given ID. If it already exists, the * existing value will be overwritten. */ Error unplaceItem(ItemPtr root, ItemPtr item, int depth = 0); + Error remove(ItemPtr item); + /** * Finds the parent an inode by its ID. */ @@ -144,6 +161,8 @@ class FileStoreTemplate: public FileStore { bool canWrite(ItemPtr existing, size_t size); + bool valid() const; + }; template @@ -195,6 +214,7 @@ Error FileStoreTemplate::decLinks(InodeId_t id) { auto item = find(id); if (item.valid()) { item->links--; + // TODO: remove item if links is 0 return OxError(0); } return OxError(1); @@ -204,7 +224,11 @@ template Error FileStoreTemplate::write(InodeId_t id, void *data, FsSize_t dataSize, uint8_t fileType) { oxTrace("ox::fs::FileStoreTemplate::write") << "Attempting to write to inode" << id; auto existing = find(id); - // TODO: try compacting if unable to write + if (canWrite(existing, dataSize)) { + compact(); + existing = find(id); + } + if (canWrite(existing, dataSize)) { // delete the old node if it exists if (existing.valid()) { @@ -255,6 +279,11 @@ Error FileStoreTemplate::write(InodeId_t id, void *data, FsSize_t dataSi return OxError(1); } +template +Error FileStoreTemplate::remove(InodeId_t id) { + return remove(find(id)); +} + template Error FileStoreTemplate::read(InodeId_t id, void *data, FsSize_t dataSize, FsSize_t *size) { oxTrace("ox::fs::FileStoreTemplate::read") << "Attempting to read from inode" << id; @@ -346,17 +375,22 @@ const ptrarith::Ptr FileStoreTemplate::read(InodeI } template -typename FileStoreTemplate::StatInfo FileStoreTemplate::stat(InodeId_t id) { +Error FileStoreTemplate::resize(std::size_t size, void *newBuff) { + return OxError(0); +} + +template +ValErr::StatInfo> FileStoreTemplate::stat(InodeId_t id) { auto inode = find(id); if (inode.valid()) { - return { + return ValErr({ .inodeId = id, .links = inode->links, .size = inode->size(), .fileType = inode->fileType, - }; + }); } - return {}; + return ValErr({}, 1); } template @@ -374,6 +408,21 @@ InodeId_t FileStoreTemplate::available() { return m_buffer->available(); } +template +ValErr FileStoreTemplate::generateInodeId() { + auto fsData = fileStoreData(); + if (fsData) { + for (auto i = 0; i < 100; i++) { + auto inode = fsData->random.gen() % MaxValue; + if (inode > ReservedInodeEnd && !find(inode).valid()) { + return inode; + } + } + return {0, OxError(2)}; + } + return {0, OxError(1)}; +} + template void FileStoreTemplate::compact() { } @@ -449,6 +498,42 @@ Error FileStoreTemplate::placeItem(ItemPtr root, ItemPtr item, int depth } } +template +Error FileStoreTemplate::unplaceItem(ItemPtr item) { + auto fsData = fileStoreData(); + if (fsData) { + auto root = m_buffer->ptr(fsData->rootNode); + if (root.valid()) { + if (root->id == item->id) { + item->left = root->left; + item->right = root->right; + auto left = m_buffer->ptr(item->left); + auto right = m_buffer->ptr(item->right); + if (right.valid()) { + auto oldRoot = fsData->rootNode; + fsData->rootNode = item->right; + if (left.valid()) { + auto err = placeItem(left); + // undo if unable to place the left side of the tree + if (err) { + fsData->rootNode = oldRoot; + return err; + } + } + } else if (left.valid()) { + fsData->rootNode = item->left; + } else { + fsData->rootNode = 0; + } + return OxError(0); + } else { + return unplaceItem(root, item); + } + } + } + return OxError(1); +} + template Error FileStoreTemplate::unplaceItem(ItemPtr root, ItemPtr item, int depth) { if (depth < 5000) { @@ -470,11 +555,20 @@ Error FileStoreTemplate::unplaceItem(ItemPtr root, ItemPtr item, int dep } else { return unplaceItem(left, item, depth + 1); } - } else { - oxTrace("ox::fs::FileStoreTemplate::unplaceItem::fail") << "Item already exists."; } + return OxError(1); } else { oxTrace("ox::fs::FileStoreTemplate::unplaceItem::fail") << "Excessive recursion depth, stopping before stack overflow."; + return OxError(1); + } +} + +template +Error FileStoreTemplate::remove(ItemPtr item) { + if (item.valid()) { + oxReturnError(unplaceItem(item)); + oxReturnError(m_buffer->free(item)); + return OxError(0); } return OxError(1); } @@ -508,10 +602,13 @@ typename FileStoreTemplate::ItemPtr FileStoreTemplate::find(Item if (depth < 5000) { if (item.valid()) { if (id > item->id) { + oxTrace("ox::fs::FileStoreTemplate::find") << "Not a match, searching on" << item->right; return find(m_buffer->ptr(item->right), id, depth + 1); } else if (id < item->id) { + oxTrace("ox::fs::FileStoreTemplate::find") << "Not a match, searching on" << item->left; return find(m_buffer->ptr(item->left), id, depth + 1); } else if (id == item->id) { + oxTrace("ox::fs::FileStoreTemplate::find") << "Found" << id << "at" << item; return item; } } else { @@ -558,6 +655,11 @@ bool FileStoreTemplate::canWrite(ItemPtr existing, size_t size) { return existing.size() >= size || m_buffer->spaceNeeded(size) <= m_buffer->available(); } +template +bool FileStoreTemplate::valid() const { + return m_buffer; +} + extern template class FileStoreTemplate; extern template class FileStoreTemplate;