ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
MMappedVector.hpp
Go to the documentation of this file.
1/**
2 * @file MMappedVector.hpp
3 * @brief Template implementation of @c MMappedVector<T>.
4 *
5 * Provides the out-of-line definitions of all @c MMappedVector<T>
6 * methods declared in @c MMappedVector.h. This file must be included
7 * by any translation unit that instantiates @c MMappedVector<T> for a
8 * specific @c T.
9 *
10 * Implemented methods:
11 * - @c MMappedVector(): open/create the backing file and map it.
12 * - @c ~MMappedVector(): sync and unmap.
13 * - @c operator[](k) const: read element @p k.
14 * - @c operator[](k): write element @p k.
15 * - @c add(): append one element, growing the file if necessary.
16 * - @c sync(): flush the backing region (@c MappedRegion::sync()).
17 *
18 * Internal helpers:
19 * - @c grow(): double the capacity and remap the backing region.
20 */
21#ifndef MMAPPED_VECTOR_HPP
22#define MMAPPED_VECTOR_HPP
23
24#include "MMappedVector.h"
25
26#include <cassert>
27#include <cerrno>
28#include <cstdint>
29#include <cstring>
30#include <new>
31#include <stdexcept>
32#include <string>
33#include <vector>
34
35#include <fcntl.h>
36#include <unistd.h>
37
38#include <sys/mman.h>
39
40template <typename T>
41MMappedVector<T>::MMappedVector(const char *filename, bool read_only,
42 uint64_t magic_value, uint16_t version)
43{
44 read_only_ = read_only;
45 auto length = region.openFile(filename, read_only);
46 bool empty = (length == 0);
47
48 if(empty) {
49 length = offsetof(data_t, d) + sizeof(T) * STARTING_CAPACITY;
50 region.resizeFile(length);
51 }
52
53 region.map(length);
54 data = reinterpret_cast<data_t *>(region.base());
55
56 if(empty) {
57 data->magic = magic_value;
58 data->version = version;
59 data->elem_size = static_cast<uint16_t>(sizeof(T));
60 data->flags = 0;
61 data->capacity = STARTING_CAPACITY;
62 data->nb_elements = 0;
63 } else {
64 if(data->magic != magic_value)
65 throw std::runtime_error("ProvSQL mmap: wrong file type (magic mismatch)");
66 if(data->version == 0 || data->version > version)
67 throw std::runtime_error("ProvSQL mmap: unsupported format version "
68 + std::to_string(data->version));
69 if(data->elem_size != sizeof(T))
70 throw std::runtime_error("ProvSQL mmap: element size mismatch (recompile required)");
71 unclean_ = (data->flags & FLAG_DIRTY) != 0;
72 }
73
74 /* Mark the file open for writing; the destructor clears it. A file
75 found dirty was left behind by a process that died mid-write, which
76 provsql.check_store() reports. */
77 if(!read_only)
78 data->flags |= FLAG_DIRTY;
79}
80
81template <typename T>
83{
84 auto new_capacity = data->capacity*2;
85 region.remap(offsetof(data_t,d)+sizeof(T)*new_capacity);
86 data = reinterpret_cast<data_t *>(region.base());
87 data->capacity = new_capacity;
89
90template <typename T>
92{
93 if(data && !read_only_)
94 data->flags &= ~FLAG_DIRTY;
95 region.close();
96}
97
98template <typename T>
99inline const T &MMappedVector<T>::operator[](unsigned long k) const
100{
101 return data->d[k];
102}
103
104template <typename T>
105inline T &MMappedVector<T>::operator[](unsigned long k)
106{
107 return data->d[k];
108}
109
110template <typename T>
111void MMappedVector<T>::add(const T &value)
112{
113 if(data->nb_elements == data->capacity)
115
116 data->d[data->nb_elements++] = value;
117}
118
119template <typename T>
121{
122 region.sync();
123}
124
125template <typename T>
127{
128 region.flush();
129}
130
131#endif /* MMAPPED_VECTOR_HPP */
Append-only vector template backed by a memory-mapped file.
uint16_t version() const
Return the format version stamped in the file's header.
~MMappedVector()
Sync and unmap the file.
data_t * data
Typed view of region.base().
void flush()
Force the backing file to stable storage (MappedRegion::flush()).
static constexpr unsigned STARTING_CAPACITY
Initial number of element slots allocated.
bool read_only_
Mapped read-only: the header must not be written.
void add(const T &value)
Append an element to the end of the vector.
static constexpr uint32_t FLAG_DIRTY
MMappedVector(const char *filename, bool read_only, uint64_t magic, uint16_t version=1)
Open (or create) the mmap-backed vector.
void grow()
Double the backing region and refresh data.
MappedRegion region
Backing storage (shared mmap, or heap buffer).
const T & operator[](unsigned long k) const
Read-only element access by index.
void sync()
Flush the backing region to its file (MappedRegion::sync()).
On-disk layout stored at the start of the backing file.
uint32_t flags
Bit 0: opened for writing and not closed since.