/** * @file MMappedVector.hpp * @brief Template implementation of @c MMappedVector. * * Provides the out-of-line definitions of all @c MMappedVector * methods declared in @c MMappedVector.h. This file must be included * by any translation unit that instantiates @c MMappedVector for a * specific @c T. * * Implemented methods: * - @c MMappedVector(): open/create the backing file and map it. * - @c ~MMappedVector(): sync and unmap. * - @c operator[](k) const: read element @p k. * - @c operator[](k): write element @p k. * - @c add(): append one element, growing the file if necessary. * - @c sync(): flush the backing region (@c MappedRegion::sync()). * * Internal helpers: * - @c grow(): double the capacity and remap the backing region. */ #ifndef MMAPPED_VECTOR_HPP #define MMAPPED_VECTOR_HPP #include "MMappedVector.h" #include #include #include #include #include #include #include #include #include #include #include template MMappedVector::MMappedVector(const char *filename, bool read_only, uint64_t magic_value) { auto length = region.openFile(filename, read_only); bool empty = (length == 0); if(empty) { length = offsetof(data_t, d) + sizeof(T) * STARTING_CAPACITY; region.resizeFile(length); } region.map(length); data = reinterpret_cast(region.base()); if(empty) { data->magic = magic_value; data->version = 1; data->elem_size = static_cast(sizeof(T)); data->_reserved = 0; data->capacity = STARTING_CAPACITY; data->nb_elements = 0; } else { if(data->magic != magic_value) throw std::runtime_error("ProvSQL mmap: wrong file type (magic mismatch)"); if(data->version != 1) throw std::runtime_error("ProvSQL mmap: unsupported format version " + std::to_string(data->version)); if(data->elem_size != sizeof(T)) throw std::runtime_error("ProvSQL mmap: element size mismatch (recompile required)"); } } template void MMappedVector::grow() { auto new_capacity = data->capacity*2; region.remap(offsetof(data_t,d)+sizeof(T)*new_capacity); data = reinterpret_cast(region.base()); data->capacity = new_capacity; } template MMappedVector::~MMappedVector() { region.close(); } template inline const T &MMappedVector::operator[](unsigned long k) const { return data->d[k]; } template inline T &MMappedVector::operator[](unsigned long k) { return data->d[k]; } template void MMappedVector::add(const T &value) { if(data->nb_elements == data->capacity) grow(); data->d[data->nb_elements++] = value; } template void MMappedVector::sync() { region.sync(); } #endif /* MMAPPED_VECTOR_HPP */