37 fd=open(filename, O_CREAT|(read_only?O_RDONLY:O_RDWR), 0600);
39 throw std::runtime_error(strerror(errno));
41 auto size = lseek(
fd, 0, SEEK_END);
42 lseek(
fd, 0, SEEK_SET);
49 if(ftruncate(
fd, size))
50 throw std::runtime_error(strerror(errno));
53 mmap(size, read_only);
56 table->magic = magic_value;
58 table->elem_size =
static_cast<uint16_t
>(
sizeof(
value_t));
61 table->nb_elements = 0;
62 table->next_value = 0;
63 for(
unsigned long i=0; i<
table->capacity(); ++i) {
67 if(
table->magic != magic_value)
68 throw std::runtime_error(
"ProvSQL mmap: wrong file type (magic mismatch)");
69 if(
table->version != 1)
70 throw std::runtime_error(
"ProvSQL mmap: unsupported format version "
71 + std::to_string(
table->version));
73 throw std::runtime_error(
"ProvSQL mmap: element size mismatch (recompile required)");
82 PROT_READ|(read_only?0:PROT_WRITE),
86 if(
table == MAP_FAILED)
87 throw std::runtime_error(strerror(errno));
94 std::vector<value_t> elements;
95 elements.reserve(
table->nb_elements);
96 for(
unsigned long i=0; i<
table->capacity(); ++i)
98 elements.push_back(
table->t[i]);
100 auto new_log_size =
table->log_size+1;
104 if(ftruncate(
fd, new_size))
105 throw std::runtime_error(strerror(errno));
106 mmap(new_size,
false);
108 table->log_size = new_log_size;
109 for(
unsigned long i=0; i<
table->capacity(); ++i) {
112 for(
const auto &u: elements)
113 set(u.uuid, u.value);
127 k = (k+1) %
table->capacity();
137 return table->t[k].value;
149 ++
table->nb_elements;
150 table->t[k].uuid = u;
151 return std::make_pair(
table->t[k].value =
table->next_value++,
true);
153 return std::make_pair(
table->t[k].value,
false);
Open-addressing hash table mapping UUIDs to integers, backed by an mmap file.
void set(pg_uuid_t u, unsigned long i)
Store the mapping u → i in the table.
unsigned long hash(pg_uuid_t u) const
Compute the starting slot index for UUID u.
void grow()
Double the table capacity and rehash all existing entries.
int fd
File descriptor of the backing mmap file.
std::pair< unsigned long, bool > add(pg_uuid_t u)
Insert UUID u, assigning it the next available integer.
MMappedUUIDHashTable(const char *filename, bool read_only, uint64_t magic)
Open (or create) the mmap-backed hash table.
static constexpr unsigned STARTING_LOG_SIZE
Initial log2 capacity (65 536 slots).
unsigned long find(pg_uuid_t u) const
Find the slot index of u, or NOTHING if absent.
unsigned long operator[](pg_uuid_t u) const
Look up the integer index for UUID u.
void mmap(size_t length, bool read_only)
Map length bytes from the backing file (read-write or read-only).
~MMappedUUIDHashTable()
Sync and unmap the file.
void sync()
Flush dirty pages to the backing file with msync().
static constexpr unsigned long NOTHING
Sentinel returned by operator[]() when the UUID is not present.
static constexpr double MAXIMUM_LOAD_FACTOR
Rehash when this fraction of slots is occupied.
table_t * table
Pointer to the memory-mapped table header.
On-disk layout of the hash table stored in the mmap file.
static constexpr unsigned logSizeForSize(std::size_t size)
Compute the log2 of the slot count from the file size.
static constexpr std::size_t sizeForLogSize(unsigned ls)
Compute the file size required for a table with 2^ls slots.
One slot in the hash table: a UUID key and its associated integer value.