uint32_t reserved_;
};
-struct Block {
-};
-
template <typename Target_>
class Offset {
private:
}
};
+struct Block {
+ Cytore::Offset<void> reserved_;
+};
+
template <typename Type_>
static _finline Type_ Round(Type_ value, Type_ size) {
Type_ mask(size - 1);
private:
int file_;
- std::vector<uint8_t *> blocks_;
+
+ typedef std::vector<uint8_t *> BlockVector_;
+ BlockVector_ blocks_;
+
+ struct Mapping_ {
+ uint8_t *data_;
+ size_t size_;
+
+ Mapping_(uint8_t *data, size_t size) :
+ data_(data),
+ size_(size)
+ {
+ }
+ };
+
+ typedef std::vector<Mapping_> MappingVector_;
+ MappingVector_ maps_;
Header &Header_() {
return *reinterpret_cast<Header *>(blocks_[0]);
size_t extend(size - before);
void *data(mmap(NULL, extend, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, file_, before));
+ _assert(data != MAP_FAILED);
+ uint8_t *bytes(reinterpret_cast<uint8_t *>(data));
+
+ maps_.push_back(Mapping_(bytes, extend));
for (size_t i(0); i != extend >> Shift_; ++i)
- blocks_.push_back(reinterpret_cast<uint8_t *>(data) + Block_ * i);
+ blocks_.push_back(bytes + Block_ * i);
}
- void Truncate_(size_t capacity) {
+ bool Truncate_(size_t capacity) {
capacity = Round(capacity, Block_);
- ftruncate(file_, capacity);
+
+ int error(ftruncate(file_, capacity));
+ if (error != 0)
+ return false;
+
Map_(capacity);
+ return true;
}
public:
}
~File() {
- // XXX: this object is never deconstructed. if it were, this should unmap the memory
+ for (typename MappingVector_::const_iterator map(maps_.begin()); map != maps_.end(); ++map)
+ munmap(map->data_, map->size_);
close(file_);
}
+ void Sync() {
+ for (typename MappingVector_::const_iterator map(maps_.begin()); map != maps_.end(); ++map)
+ msync(map->data_, map->size_, MS_SYNC);
+ }
+
size_t Capacity() const {
return blocks_.size() * Block_;
}
void Open(const char *path) {
_assert(file_ == -1);
file_ = open(path, O_RDWR | O_CREAT | O_EXLOCK, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ _assert(file_ != -1);
struct stat stat;
- fstat(file_, &stat);
+ _assert(fstat(file_, &stat) == 0);
size_t core(sizeof(Header) + sizeof(Base_));
size_t size(stat.st_size);
if (size == 0) {
- Truncate_(core);
+ _assert(Truncate_(core));
Header_().magic_ = Magic;
Size_() = core;
} else {
_assert(size >= core);
- Truncate_(size);
+ // XXX: this involves an unneccessary call to ftruncate()
+ _assert(Truncate_(size));
_assert(Header_().magic_ == Magic);
_assert(Header_().version_ == 0);
}
}
- void Reserve(size_t capacity) {
+ bool Reserve(size_t capacity) {
if (capacity <= Capacity())
- return;
+ return true;
+
+ uint8_t *block(blocks_.back());
blocks_.pop_back();
- Truncate_(capacity);
+
+ if (Truncate_(capacity))
+ return true;
+ else {
+ blocks_.push_back(block);
+ return false;
+ }
}
template <typename Target_>
Target_ &Get(uint32_t offset) {
- return *reinterpret_cast<Target_ *>(blocks_[offset >> Shift_] + (offset & Mask_));
+ return *reinterpret_cast<Target_ *>(offset == 0 ? NULL : blocks_[offset >> Shift_] + (offset & Mask_));
}
template <typename Target_>
Offset<Target_> New(size_t extra = 0) {
size_t size(sizeof(Target_) + extra);
size = Round(size, sizeof(uintptr_t));
- Reserve(Size_() + size);
- uint32_t offset(Size_());
- Size_() += size;
+
+ uint32_t offset;
+ if (!Reserve(Size_() + size))
+ offset = 0;
+ else {
+ offset = Size_();
+ Size_() += size;
+ }
+
return Offset<Target_>(offset);
}
};