From d5cbe0e7a2369caa0e3652776beb114f5354a6e4 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 6 Jul 2016 19:44:33 -0500 Subject: [PATCH] Add file type to FileStore::stat --- src/ox/fs/filestore.hpp | 168 +++++++++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 38 deletions(-) diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index eee1175c8..87bdcd5d8 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -22,17 +22,17 @@ class FileStore { struct StatInfo { InodeId_t inodeId; FsSize_t size; + ox::std::uint8_t fileType; }; private: struct Inode { // the next Inode in memory FsSize_t prev, next; - - // The following variables should not be assumed to exist FsSize_t dataLen; InodeId_t m_id; ox::std::uint8_t refs; + ox::std::uint8_t fileType; FsSize_t left, right; FsSize_t size(); @@ -46,7 +46,6 @@ class FileStore { ox::std::uint32_t m_fsType; FsSize_t m_size; - FsSize_t m_firstInode; FsSize_t m_rootInode; public: @@ -56,7 +55,7 @@ class FileStore { * @param data the contents of the file * @param dataLen the number of bytes data points to */ - int write(void *data, FsSize_t dataLen); + int write(void *data, FsSize_t dataLen, ox::std::uint8_t fileType = 0); /** * Writes the given data to a "file" with the given id. @@ -64,7 +63,7 @@ class FileStore { * @param data the contents of the file * @param dataLen the number of bytes data points to */ - int write(InodeId_t id, void *data, FsSize_t dataLen); + int write(InodeId_t id, void *data, FsSize_t dataLen, ox::std::uint8_t fileType = 0); /** * Removes the inode of the given ID. @@ -104,6 +103,15 @@ class FileStore { */ Inode *getInode(Inode *root, InodeId_t id); + /** + * Gets the inode at the given id. + * @param root the root node to start comparing on + * @param id id of the "file" + * @param pathLen number of characters in pathLen + * @return the requested Inode, if available + */ + Inode *getInodeParent(Inode *root, InodeId_t id); + /** * Removes the inode of the given ID. * @param id the id of the file @@ -116,6 +124,12 @@ class FileStore { */ void unlink(Inode *node); + /** + * Gets the address of the next available inode, assuming there is a next + * available inode. + */ + FsSize_t nextInodeAddr(); + /** * Gets an address for a new Inode. * @param size the size of the Inode @@ -123,9 +137,9 @@ class FileStore { void *alloc(FsSize_t size); /** - * Compresses all of the inode into a contiguous space, starting at m_firstInode. + * Compresses all of the inode into a contiguous space, starting at the first inode. */ - void compress(); + void compress(FsSize_t firstInode); /** * Inserts the given insertValue into the tree of the given root. @@ -140,10 +154,15 @@ class FileStore { */ FsSize_t iterator(); - Inode *firstInode(); + FsSize_t firstInode(); Inode *lastInode(); + /** + * Updates the address of the inode in the tree. + */ + void updateInodeAddress(InodeId_t id, FsSize_t addr); + ox::std::uint8_t *begin() { return (ox::std::uint8_t*) this; } @@ -193,19 +212,21 @@ void *FileStore::Inode::data() { // FileStore template -int FileStore::write(void *data, FsSize_t dataLen) { +int FileStore::write(void *data, FsSize_t dataLen, ox::std::uint8_t fileType) { return 1; } template -int FileStore::write(InodeId_t id, void *data, FsSize_t dataLen) { +int FileStore::write(InodeId_t id, void *data, FsSize_t dataLen, ox::std::uint8_t fileType) { auto retval = 1; const FsSize_t size = sizeof(Inode) + dataLen; auto inode = (Inode*) alloc(size); if (inode) { - auto root = ptr(m_rootInode); + remove(id); inode->m_id = id; + inode->fileType = fileType; inode->setData(data, dataLen); + auto root = ptr(m_rootInode); if (insert(root, inode) || root == inode) { retval = 0; } @@ -228,7 +249,7 @@ int FileStore::remove(Inode *root, InodeId_t id) { if (node->m_id != id) { err = remove(node, id); } else { - root->left = node->left; + root->left = 0; if (node->right) { insert(root, ptr(node->right)); } @@ -236,6 +257,9 @@ int FileStore::remove(Inode *root, InodeId_t id) { insert(root, ptr(node->left)); } unlink(node); + node->m_id = 0; + node->left = 0; + node->right = 0; err = 0; } } @@ -245,7 +269,7 @@ int FileStore::remove(Inode *root, InodeId_t id) { if (node->m_id != id) { err = remove(node, id); } else { - root->right = node->right; + root->right = 0; if (node->right) { insert(root, ptr(node->right)); } @@ -253,15 +277,21 @@ int FileStore::remove(Inode *root, InodeId_t id) { insert(root, ptr(node->left)); } unlink(node); + node->m_id = 0; + node->left = 0; + node->right = 0; err = 0; } } - } else { + } else if (ptr(m_rootInode)->m_id == id) { m_rootInode = root->right; if (root->left) { insert(ptr(m_rootInode), ptr(root->left)); } unlink(root); + root->m_id = 0; + root->left = 0; + root->right = 0; err = 0; } @@ -269,11 +299,27 @@ int FileStore::remove(Inode *root, InodeId_t id) { } template -void FileStore::unlink(Inode *node) { - auto next = ptr(node->next); - auto prev = ptr(node->prev); +void FileStore::unlink(Inode *inode) { + auto next = ptr(inode->next); + auto prev = ptr(inode->prev); prev->next = ptr(next); next->prev = ptr(prev); + + ox::std::memset(inode, 0, inode->size()); + inode->prev = firstInode(); + inode->next = firstInode(); +} + +template +void FileStore::updateInodeAddress(InodeId_t id, FsSize_t addr) { + auto parent = getInodeParent(ptr(m_rootInode), id); + if (parent) { + if (parent->left && ptr(parent->left)->m_id == id) { + parent->left = addr; + } else if (parent->right && ptr(parent->right)->m_id == id) { + parent->right = addr; + } + } } template @@ -296,6 +342,7 @@ typename FileStore::StatInfo FileStore::stat(InodeId_t id) { StatInfo stat; if (inode) { stat.size = inode->dataLen; + stat.fileType = inode->fileType; stat.inodeId = id; } else { stat.inodeId = 0; @@ -322,36 +369,79 @@ typename FileStore::Inode *FileStore::getInode(Inode *root, return retval; } +template +typename FileStore::Inode *FileStore::getInodeParent(Inode *root, InodeId_t id) { + Inode *retval = nullptr; + + if (root->m_id > id) { + if (root->left) { + if (ptr(root->left)->m_id == id) { + retval = root; + } else { + retval = getInode(ptr(root->left), id); + } + } + } else if (root->m_id < id) { + if (root->right) { + if (ptr(root->right)->m_id == id) { + retval = root; + } else { + retval = getInode(ptr(root->right), id); + } + } + } + + return retval; +} + +template +FsSize_t FileStore::nextInodeAddr() { + FsSize_t next = ptr(lastInode()) + lastInode()->size(); + return next; +} + template void *FileStore::alloc(FsSize_t size) { - if ((lastInode()->next + size) > (ox::std::uint64_t) end()) { - compress(); - if ((lastInode()->next + size) > (ox::std::uint64_t) end()) { + FsSize_t next = nextInodeAddr(); + if ((next + size) > (ox::std::uint64_t) end()) { + compress(firstInode()); + next = nextInodeAddr(); + if ((next + size) > (ox::std::uint64_t) end()) { return nullptr; } } - const auto retval = lastInode()->next; + const auto retval = next; const auto inode = ptr(retval); ox::std::memset(inode, 0, size); + inode->prev = ptr(firstInode())->prev; inode->next = retval + size; - ptr(m_firstInode)->prev = retval; + ptr(firstInode())->prev = retval; return inode; } template -void FileStore::compress() { - auto current = ptr(m_firstInode); - while (current->next) { - auto prevEnd = current + current->size(); - auto prev = ptr(current); - current->next = ptr(current) + current->size(); - current = ptr(current->next); - current->prev = prev; - if (prevEnd != current) { - ox::std::memcpy(prevEnd, current, current->size()); - current = prevEnd; +void FileStore::compress(FsSize_t start) { + auto dest = ptr(firstInode()); + auto current = ptr(start); + while (current->next > ptr(begin()) && current->next < ptr(end())) { + ox::std::memcpy(dest, current, current->size()); + if (dest->next != firstInode()) { + dest->next = ptr(dest) + dest->size(); } + ptr(dest->next)->prev = ptr(dest); + current = ptr(dest->next); + dest = ptr(ptr(dest) + dest->size()); + updateInodeAddress(dest->m_id, ptr(dest)); + //auto prevEnd = current + current->size(); + //auto prev = ptr(current); + //current->next = ptr(current) + current->size(); + //current = ptr(current->next); + //current->prev = prev; + //if (prevEnd != current) { + // ox::std::memcpy(prevEnd, current, current->size()); + // current = prevEnd; + //} } } @@ -373,6 +463,9 @@ bool FileStore::insert(Inode *root, Inode *insertValue) { root->right = ptr(insertValue); retval = true; } + } else if (m_rootInode == 0) { + m_rootInode = ptr(insertValue); + retval = true; } return retval; @@ -389,13 +482,13 @@ FsSize_t FileStore::ptr(void *ptr) { } template -typename FileStore::Inode *FileStore::firstInode() { - return ptr(sizeof(FileStore)); +FsSize_t FileStore::firstInode() { + return sizeof(FileStore); } template typename FileStore::Inode *FileStore::lastInode() { - return ptr(ptr(m_firstInode)->prev); + return ptr(ptr(firstInode())->prev); } template @@ -411,8 +504,7 @@ ox::std::uint8_t *FileStore::format(ox::std::uint8_t *buffer, FsSize_t fs->m_fsType = fsType; fs->m_size = size; fs->m_rootInode = sizeof(FileStore); - fs->m_firstInode = sizeof(FileStore); - fs->firstInode()->prev = fs->m_firstInode; + ((Inode*) (fs + 1))->prev = fs->firstInode(); fs->lastInode()->next = sizeof(FileStore); return (ox::std::uint8_t*) buffer;