Flesh out new file store's alloc

This commit is contained in:
Gary Talent 2018-03-06 23:07:39 -06:00
parent c5bf8591e3
commit 3151b5508e
8 changed files with 204 additions and 72 deletions

View File

@ -15,6 +15,10 @@ if(OX_BUILD_EXEC STREQUAL "OFF" OR OX_USE_STDLIB STREQUAL "OFF")
set(OX_RUN_TESTS "OFF") set(OX_RUN_TESTS "OFF")
endif() endif()
if(OX_USE_STDLIB STREQUAL "ON")
add_definitions(-DOX_USE_STDLIB)
endif()
if(NOT MSVC) if(NOT MSVC)
add_definitions( add_definitions(
-std=c++11 -std=c++11

View File

@ -24,9 +24,9 @@ class FileStore {
uint8_t fileType; uint8_t fileType;
}; };
virtual bool valid(InodeId_t size) = 0; virtual Error format() = 0;
virtual void resize(InodeId_t size = 0) = 0; virtual Error setSize(InodeId_t size) = 0;
virtual Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0) = 0; virtual Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0) = 0;

View File

@ -17,14 +17,19 @@ template<typename size_t>
class FileStoreTemplate: public FileStore { class FileStoreTemplate: public FileStore {
private: private:
struct __attribute__((packed)) FileStoreData {
ox::LittleEndian<size_t> rootNode = sizeof(LinkedList<size_t>);
};
size_t m_buffSize = 0;
ox::fs::LinkedList<size_t> *m_linkedList = nullptr; ox::fs::LinkedList<size_t> *m_linkedList = nullptr;
public: public:
FileStoreTemplate(void *buff); FileStoreTemplate(void *buff, size_t buffSize);
bool valid(InodeId_t size); Error format();
void resize(InodeId_t size = 0); Error setSize(InodeId_t buffSize);
Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0); Error write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0);
@ -44,55 +49,96 @@ class FileStoreTemplate: public FileStore {
InodeId_t available(); InodeId_t available();
private:
FileStoreData &fileStoreData();
}; };
template<typename size_t> template<typename size_t>
FileStoreTemplate<size_t>::FileStoreTemplate(void *buff) { FileStoreTemplate<size_t>::FileStoreTemplate(void *buff, size_t buffSize) {
m_buffSize = buffSize;
m_linkedList = static_cast<ox::fs::LinkedList<size_t>*>(buff); m_linkedList = static_cast<ox::fs::LinkedList<size_t>*>(buff);
if (!m_linkedList->valid(buffSize)) {
m_buffSize = 0;
m_linkedList = nullptr;
}
} }
template<typename size_t> template<typename size_t>
bool FileStoreTemplate<size_t>::valid(size_t size) { Error FileStoreTemplate<size_t>::format() {
return false; Error err = 0;
auto data = m_linkedList->malloc(sizeof(FileStoreData));
if (data.valid()) {
new (data->data()) FileStoreData;
} else {
err = 1;
}
return err;
} }
void FileStoreTemplate<size_t>::resize(InodeId_t size = 0) { template<typename size_t>
Error FileStoreTemplate<size_t>::setSize(InodeId_t size) {
Error err = 0;
if (m_buffSize >= size) {
err |= m_linkedList->setSize(size);
} else {
err = 1;
}
return err;
} }
Error FileStoreTemplate<size_t>::write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType = 0) { template<typename size_t>
Error FileStoreTemplate<size_t>::write(InodeId_t id, void *data, InodeId_t dataLen, uint8_t fileType) {
return 1; return 1;
} }
template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(InodeId_t id) { Error FileStoreTemplate<size_t>::incLinks(InodeId_t id) {
return 1; return 1;
} }
template<typename size_t>
Error FileStoreTemplate<size_t>::decLinks(InodeId_t id) { Error FileStoreTemplate<size_t>::decLinks(InodeId_t id) {
return 1; return 1;
} }
template<typename size_t>
Error FileStoreTemplate<size_t>::read(InodeId_t id, void *data, InodeId_t *size) { Error FileStoreTemplate<size_t>::read(InodeId_t id, void *data, InodeId_t *size) {
return 1; return 1;
} }
template<typename size_t>
Error FileStoreTemplate<size_t>::read(InodeId_t id, InodeId_t readStart, InodeId_t readSize, void *data, InodeId_t *size) { Error FileStoreTemplate<size_t>::read(InodeId_t id, InodeId_t readStart, InodeId_t readSize, void *data, InodeId_t *size) {
return 1; return 1;
} }
StatInfo FileStoreTemplate<size_t>::stat(InodeId_t id) { template<typename size_t>
typename FileStoreTemplate<size_t>::StatInfo FileStoreTemplate<size_t>::stat(InodeId_t id) {
return {}; return {};
} }
template<typename size_t>
InodeId_t FileStoreTemplate<size_t>::spaceNeeded(InodeId_t size) { InodeId_t FileStoreTemplate<size_t>::spaceNeeded(InodeId_t size) {
return 1; return 1;
} }
template<typename size_t>
InodeId_t FileStoreTemplate<size_t>::size() { InodeId_t FileStoreTemplate<size_t>::size() {
return 1; return 1;
} }
template<typename size_t>
InodeId_t FileStoreTemplate<size_t>::available() { InodeId_t FileStoreTemplate<size_t>::available() {
return 1; return 1;
} }
template<typename size_t>
typename FileStoreTemplate<size_t>::FileStoreData &FileStoreTemplate<size_t>::fileStoreData() {
return *reinterpret_cast<FileStoreData*>(m_linkedList->firstItem());
}
using FileStore16 = FileStoreTemplate<uint16_t>;
using FileStore32 = FileStoreTemplate<uint32_t>;
using FileStore64 = FileStoreTemplate<uint64_t>;
} }

View File

@ -20,24 +20,36 @@ class __attribute__((packed)) LinkedList {
friend LinkedList; friend LinkedList;
public: public:
ox::LittleEndian<size_t> size = sizeof(Item); ox::LittleEndian<size_t> m_size = sizeof(Item);
protected: protected:
ox::LittleEndian<size_t> prev = 0; ox::LittleEndian<size_t> prev = 0;
ox::LittleEndian<size_t> next = 0; ox::LittleEndian<size_t> next = 0;
public:
explicit Item(size_t size) { explicit Item(size_t size) {
this->size = size; this->m_size = size;
}
size_t size() const {
return m_size;
}
ox::fs::Ptr<uint8_t, size_t> data() {
return Ptr<uint8_t, size_t>(this, m_size, sizeof(*this), m_size - sizeof(*this));
} }
}; };
private: private:
struct __attribute__((packed)) Header { struct __attribute__((packed)) Header {
ox::LittleEndian<size_t> size = sizeof(Header); ox::LittleEndian<size_t> size = sizeof(Header);
ox::LittleEndian<size_t> bytesUsed = sizeof(Header);
ox::LittleEndian<size_t> firstItem = 0; ox::LittleEndian<size_t> firstItem = 0;
}; };
struct ItemPtr: public ox::fs::Ptr<Item, size_t> { struct ItemPtr: public ox::fs::Ptr<Item, size_t> {
inline ItemPtr() = default;
inline ItemPtr(void *dataStart, size_t dataSize, size_t itemOffset, size_t size): inline ItemPtr(void *dataStart, size_t dataSize, size_t itemOffset, size_t size):
Ptr<Item, size_t>(dataStart, dataSize, itemOffset, size) { Ptr<Item, size_t>(dataStart, dataSize, itemOffset, size) {
} }
@ -46,8 +58,10 @@ class __attribute__((packed)) LinkedList {
// make sure this can be read as an Item, and then use Item::size for the size // make sure this can be read as an Item, and then use Item::size for the size
auto itemSpace = dataSize - itemOffset; auto itemSpace = dataSize - itemOffset;
auto item = reinterpret_cast<Item*>(static_cast<uint8_t*>(dataStart) + itemOffset); auto item = reinterpret_cast<Item*>(static_cast<uint8_t*>(dataStart) + itemOffset);
if (itemSpace >= static_cast<size_t>(sizeof(Item)) and itemSpace >= item->size) { if (itemOffset >= sizeof(Header) and
this->init(dataStart, dataSize, itemOffset, item->size); itemSpace >= static_cast<size_t>(sizeof(Item)) and
itemSpace >= item->size()) {
this->init(dataStart, dataSize, itemOffset, item->size());
} else { } else {
this->init(dataStart, dataSize, 0, 0); this->init(dataStart, dataSize, 0, 0);
} }
@ -63,18 +77,31 @@ class __attribute__((packed)) LinkedList {
ItemPtr firstItem(); ItemPtr firstItem();
ItemPtr lastItem();
ItemPtr prev(Item *item); ItemPtr prev(Item *item);
ItemPtr next(Item *item); ItemPtr next(Item *item);
ItemPtr ptr(size_t offset); ItemPtr ptr(size_t offset);
ItemPtr ptr(uint8_t *item); ItemPtr ptr(void *item);
ItemPtr malloc(size_t size); ItemPtr malloc(size_t size);
void free(ItemPtr item); void free(ItemPtr item);
bool valid(size_t maxSize);
Error setSize(size_t size);
size_t size();
/**
* @return the bytes still available in this LinkedList
*/
size_t available();
private: private:
void compact(void (*cb)(ItemPtr itemMoved)); void compact(void (*cb)(ItemPtr itemMoved));
@ -92,6 +119,15 @@ typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::firstItem() {
return ptr(m_header.firstItem); return ptr(m_header.firstItem);
} }
template<typename size_t>
typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::lastItem() {
auto first = ptr(m_header.firstItem);
if (first.valid()) {
return prev(first);
}
return ItemPtr();
}
template<typename size_t> template<typename size_t>
typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::prev(Item *item) { typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::prev(Item *item) {
return ptr(item->prev); return ptr(item->prev);
@ -108,21 +144,62 @@ typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::ptr(size_t offset) {
} }
template<typename size_t> template<typename size_t>
typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::ptr(uint8_t *item) { typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::ptr(void *item) {
return ItemPtr(this, m_header.size, reinterpret_cast<size_t>(item - static_cast<uint8_t*>(this))); return ItemPtr(this, m_header.size, reinterpret_cast<size_t>(static_cast<uint8_t*>(item) - static_cast<uint8_t*>(this)));
} }
template<typename size_t> template<typename size_t>
typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::malloc(size_t size) { typename LinkedList<size_t>::ItemPtr LinkedList<size_t>::malloc(size_t size) {
size += sizeof(Item);
if (m_header.size - m_header.bytesUsed >= size) {
if (!m_header.firstItem) { if (!m_header.firstItem) {
m_header.firstItem = sizeof(m_header); m_header.firstItem = sizeof(m_header);
} }
auto out = ItemPtr(this, m_header.size, m_header.firstItem, size); auto out = ItemPtr(this, m_header.size, m_header.firstItem, size);
if (out.valid()) { if (out.valid()) {
new (out) Item(size); new (out) Item(size);
auto first = firstItem();
auto last = lastItem();
out->next = first;
out->prev = last;
first->prev = out;
last->next = out;
m_header.bytesUsed += out.size();
} }
return out; return out;
} }
return ItemPtr();
}
template<typename size_t>
void LinkedList<size_t>::free(ItemPtr item) {
auto prev = this->prev(item);
auto next = this->next(item);
prev->next = next;
next->prev = prev;
m_header.bytesUsed -= item.size();
}
template<typename size_t>
Error LinkedList<size_t>::setSize(size_t size) {
auto last = lastItem();
if ((last.valid() and last.end() >= size) or size < sizeof(m_header)) {
return 1;
} else {
m_header.size = size;
return 0;
}
}
template<typename size_t>
bool LinkedList<size_t>::valid(size_t maxSize) {
return m_header.size <= maxSize;
}
template<typename size_t>
size_t LinkedList<size_t>::available() {
return m_header.size - m_header.bytesUsed;
}
template<typename size_t> template<typename size_t>
void LinkedList<size_t>::compact(void (*cb)(ItemPtr)) { void LinkedList<size_t>::compact(void (*cb)(ItemPtr)) {

View File

@ -18,7 +18,7 @@ class Ptr {
private: private:
uint8_t *m_dataStart = nullptr; uint8_t *m_dataStart = nullptr;
size_t m_itemStart = 0; size_t m_itemOffset = 0;
size_t m_itemSize = 0; size_t m_itemSize = 0;
public: public:
@ -32,6 +32,8 @@ class Ptr {
inline size_t offset() const; inline size_t offset() const;
inline size_t end();
inline T *operator->() const; inline T *operator->() const;
inline operator T*() const; inline operator T*() const;
@ -40,10 +42,6 @@ class Ptr {
inline T &operator*() const; inline T &operator*() const;
inline Ptr &operator=(size_t offset);
inline Ptr &operator+=(size_t offset);
protected: protected:
void init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize); void init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize);
@ -56,7 +54,7 @@ inline Ptr<T, size_t>::Ptr(void *dataStart, size_t dataSize, size_t itemStart, s
template<typename T, typename size_t> template<typename T, typename size_t>
inline bool Ptr<T, size_t>::valid() const { inline bool Ptr<T, size_t>::valid() const {
return m_dataStart and m_itemStart; return m_dataStart and m_itemOffset;
} }
template<typename T, typename size_t> template<typename T, typename size_t>
@ -66,24 +64,29 @@ inline size_t Ptr<T, size_t>::size() const {
template<typename T, typename size_t> template<typename T, typename size_t>
inline size_t Ptr<T, size_t>::offset() const { inline size_t Ptr<T, size_t>::offset() const {
return m_itemStart; return m_itemOffset;
}
template<typename T, typename size_t>
inline size_t Ptr<T, size_t>::end() {
return m_itemOffset + m_itemSize;
} }
template<typename T, typename size_t> template<typename T, typename size_t>
inline T *Ptr<T, size_t>::operator->() const { inline T *Ptr<T, size_t>::operator->() const {
ox_assert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())"); ox_assert(valid(), "Invalid pointer access. (ox::fs::Ptr::operator->())");
return reinterpret_cast<T*>(m_dataStart + m_itemStart); return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
} }
template<typename T, typename size_t> template<typename T, typename size_t>
inline Ptr<T, size_t>::operator T*() const { inline Ptr<T, size_t>::operator T*() const {
return reinterpret_cast<T*>(m_dataStart + m_itemStart); return reinterpret_cast<T*>(m_dataStart + m_itemOffset);
} }
template<typename T, typename size_t> template<typename T, typename size_t>
inline Ptr<T, size_t>::operator size_t() const { inline Ptr<T, size_t>::operator size_t() const {
if (valid()) { if (valid()) {
return m_itemStart; return m_itemOffset;
} }
return 0; return 0;
} }
@ -94,26 +97,14 @@ inline T &Ptr<T, size_t>::operator*() const {
return *static_cast<T>(this); return *static_cast<T>(this);
} }
template<typename T, typename size_t>
inline Ptr<T, size_t> &Ptr<T, size_t>::operator=(size_t offset) {
m_itemStart = offset;
return *this;
}
template<typename T, typename size_t>
inline Ptr<T, size_t> &Ptr<T, size_t>::operator+=(size_t offset) {
m_itemStart += offset;
return *this;
}
template<typename T, typename size_t> template<typename T, typename size_t>
void Ptr<T, size_t>::init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize) { void Ptr<T, size_t>::init(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize) {
// do some sanity checks before assuming this is valid // do some sanity checks before assuming this is valid
m_dataStart = static_cast<uint8_t*>(dataStart);
if (itemSize >= sizeof(T) and if (itemSize >= sizeof(T) and
dataStart and dataStart and
itemStart + itemSize <= dataSize) { itemStart + itemSize <= dataSize) {
m_dataStart = static_cast<uint8_t*>(dataStart); m_itemOffset = itemStart;
m_itemStart = itemStart;
m_itemSize = itemSize; m_itemSize = itemSize;
} }
} }

View File

@ -6,6 +6,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
// make sure asserts are enabled for the test file
#undef NDEBUG
#include <iostream> #include <iostream>
#include <assert.h> #include <assert.h>
#include <map> #include <map>
@ -14,6 +17,8 @@
#include <ox/fs/fs.hpp> #include <ox/fs/fs.hpp>
#include <ox/std/std.hpp> #include <ox/std/std.hpp>
#include <ox/fs/filestore/filestore.hpp> #include <ox/fs/filestore/filestore.hpp>
#include <ox/fs/filestore/filestoretemplate.hpp>
using namespace std; using namespace std;
using namespace ox; using namespace ox;
@ -330,12 +335,24 @@ map<string, int(*)(string)> tests = {
{ {
"LinkedList::insert", "LinkedList::insert",
[](string) { [](string) {
int err = 0;
constexpr auto buffLen = 5000; constexpr auto buffLen = 5000;
uint8_t buff[buffLen]; uint8_t buff[buffLen];
auto list = new (buff) ox::fs::LinkedList<uint32_t>(buffLen); auto list = new (buff) ox::fs::LinkedList<uint32_t>(buffLen);
assert(list->malloc(50).valid()); err |= !(list->malloc(50).valid());
assert(list->firstItem().valid()); err |= !(list->firstItem().valid());
assert(list->firstItem()->size == 50); err |= !(list->firstItem()->size() == 50);
return err;
}
},
{
"FileStore::readWrite",
[](string) {
constexpr auto buffLen = 5000;
uint8_t buff[buffLen];
auto list = new (buff) ox::fs::LinkedList<uint32_t>(buffLen);
ox::fs::FileStore32 fileStore(list, buffLen);
ox_assert(fileStore.format() == 0, "Filestore::format failed.");
return 0; return 0;
} }
}, },

View File

@ -10,7 +10,7 @@
void oxAssert(const char *file, int line, bool pass, const char *msg); void oxAssert(const char *file, int line, bool pass, const char *msg);
#ifdef NDEBUG #ifndef NDEBUG
#define ox_assert(pass, msg) oxAssert(__FILE__, __LINE__, pass, msg) #define ox_assert(pass, msg) oxAssert(__FILE__, __LINE__, pass, msg)
#else #else
#define ox_assert(pass, msg) #define ox_assert(pass, msg)

View File

@ -86,10 +86,19 @@ class __attribute__((packed)) LittleEndian {
public: public:
inline LittleEndian() = default; inline LittleEndian() = default;
inline LittleEndian(const LittleEndian &other) {
m_value = other.m_value;
}
inline LittleEndian(T value) { inline LittleEndian(T value) {
m_value = ox::bigEndianAdapt(value); m_value = ox::bigEndianAdapt(value);
} }
inline const LittleEndian &operator=(const LittleEndian &other) {
m_value = other.m_value;
return *this;
}
inline T operator=(T value) { inline T operator=(T value) {
m_value = ox::bigEndianAdapt(value); m_value = ox::bigEndianAdapt(value);
return value; return value;
@ -99,41 +108,29 @@ class __attribute__((packed)) LittleEndian {
return ox::bigEndianAdapt(m_value); return ox::bigEndianAdapt(m_value);
} }
inline T operator+(T value) const { template<typename I>
return ox::bigEndianAdapt(m_value) + value; inline T operator+=(I other) {
}
inline T operator+=(T other) {
auto newVal = *this + other; auto newVal = *this + other;
m_value = ox::bigEndianAdapt(newVal); m_value = ox::bigEndianAdapt(newVal);
return newVal; return newVal;
} }
inline T operator-(T value) const { template<typename I>
return ox::bigEndianAdapt(m_value) - value; inline T operator-=(I other) {
}
inline T operator-=(T other) {
auto newVal = *this - other; auto newVal = *this - other;
m_value = ox::bigEndianAdapt(newVal); m_value = ox::bigEndianAdapt(newVal);
return newVal; return newVal;
} }
inline T operator*(T value) const { template<typename I>
return ox::bigEndianAdapt(m_value) * value; inline T operator*=(I other) {
}
inline T operator*=(T other) {
auto newVal = *this * other; auto newVal = *this * other;
m_value = ox::bigEndianAdapt(newVal); m_value = ox::bigEndianAdapt(newVal);
return newVal; return newVal;
} }
inline T operator/(T value) const { template<typename I>
return ox::bigEndianAdapt(m_value) / value; inline T operator/=(I other) {
}
inline T operator/=(T other) {
auto newVal = *this / other; auto newVal = *this / other;
m_value = ox::bigEndianAdapt(newVal); m_value = ox::bigEndianAdapt(newVal);
return newVal; return newVal;