|
|
- #pragma once
- #include <stdint.h>
- #include <endian.hpp>
- #include <string>
- #include <iostream>
- #include <assert.h>
-
- // Unix-y stuff
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
-
- struct errno_exception : public std::runtime_error {
- errno_exception(int err)
- : runtime_error{std::string{"errno with value "}+std::to_string(err)}
- {}
- };
-
- void throw_errno_if(bool pred)
- {
- if(pred)
- {
- throw errno_exception{errno};
- }
- }
-
- constexpr size_t page_size = 4096;
-
- struct [[gnu::packed]] record_identifier{
- bitops::regulated<uint32_t> x = 0;
- bitops::regulated<uint32_t> y = 0;
- std::array<uint8_t, 16> uuid = {0};
- };
-
- template<>
- struct std::hash<record_identifier> {
- uint64_t operator() (const record_identifier& value) {
- uint64_t v = *(uint32_t*)&value.x.internal;
-
- v <<= 4;
- v += *(uint32_t*)&value.y.internal;
- v ^= *(uint64_t*)&value.uuid;
- v ^= *(((uint64_t*)&value.uuid)+1);
-
- return v;
- }
- };
-
- struct record{
- record()
- {}
- union{
- std::array<uint8_t, 24> full;
- record_identifier split = record_identifier();
- } record_head;
- bitops::regulated<uint64_t> timestamp = 0;
- size_t offset = 0;
- };
-
- using db_page = std::array<uint8_t, 16384>;
-
- template<typename T>
- struct mmap_ptr{
- T* start = nullptr;
- size_t offset = 0;
-
- T& operator*(){
- return start[offset];
- }
-
- T& operator[](const size_t& n){
- return start[offset+n];
- }
-
- mmap_ptr operator+(size_t offset) {
- mmap_ptr ret;
- ret.start = start;
- ret.offset = offset + this->offset;
- return ret;
- }
-
- mmap_ptr operator++() {
- offset+=1;
- mmap_ptr ret = *this;
- return ret;
- }
-
- mmap_ptr operator++(int) {
- mmap_ptr ret = *this;
- offset+=1;
- return ret;
- }
-
- bool operator==(const mmap_ptr& oth) {
- return (start == oth.start) && (offset == oth.offset);
- }
-
- bool operator!=(const mmap_ptr& oth) {
- return !(*this == oth);
- }
- };
-
- template<typename T>
- class mmap_array : public mmap_ptr<T>
- {
- size_t mapping_size = 0;
- int fd = 0;
-
- size_t item_size = 0;
-
- public:
- mmap_array() = default;
-
- mmap_array(size_t nb_elem, const std::string& filename)
- : mmap_ptr<T>() {
- const size_t expected_size = nb_elem*sizeof(T);
- const size_t expected_size_mod = expected_size + (
- (expected_size%page_size != 0)?
- page_size - expected_size%page_size
- : 0
- );
- fd = open(
- filename.c_str(),
- O_RDWR | O_CREAT,
- S_ISUID + S_ISGID + S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP
- );
- throw_errno_if(fd < 0);
-
- struct stat data;
- int status = fstat(fd, &data);
- throw_errno_if(status < 0);
-
- if((size_t)data.st_size < expected_size_mod)
- {
- status = ftruncate(fd, expected_size_mod);
- throw_errno_if(status < 0);
- }
-
- this->start = (T*)mmap(NULL, expected_size_mod, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- throw_errno_if(this->start == nullptr);
- mapping_size = expected_size_mod;
- item_size = mapping_size / sizeof(T);
-
- auto map_access = MADV_RANDOM;
-
- if(expected_size_mod <= 1 << 20) {
- map_access |= MADV_WILLNEED;
- }
-
- #ifdef MADV_DONTDUMP
- map_access |= MADV_DONTDUMP;
- #endif
-
- this->offset = 0;
-
- posix_madvise(this->start, mapping_size, map_access);
- }
-
- void enforce_caching() {
- posix_madvise(this->start, mapping_size, MADV_WILLNEED);
- }
-
- constexpr size_t size() {
- return item_size;
- }
-
- constexpr mmap_ptr<T> begin() const {
- mmap_ptr<T> ret = *this;
- return ret;
- }
-
- constexpr mmap_ptr<T> end() const {
- mmap_ptr<T> ret = *this;
- return ret+item_size;
- }
-
- void clear() {
- munmap(this->start, mapping_size);
- close(fd);
- }
-
- ~mmap_array() {
- //std::cerr << "unmapping disabled" << std::endl;
- if(false)//this->start != nullptr)
- {
- munmap(this->start, mapping_size);
- close(fd);
- }
- }
- };
-
|