23#ifndef MAPPED_REGION_H
24#define MAPPED_REGION_H
38#ifndef PROVSQL_INPROCESS_STORE
53 if(fcntl(fd, F_FULLFSYNC) == 0)
76std::size_t
openFile(
const char *filename,
bool read_only) {
78 fd_ = open(filename, O_CREAT | (read_only ? O_RDONLY : O_RDWR), 0600);
80 throw std::runtime_error(strerror(errno));
81 auto size = lseek(
fd_, 0, SEEK_END);
82 lseek(
fd_, 0, SEEK_SET);
83 return static_cast<std::size_t
>(size);
97#ifdef PROVSQL_INPROCESS_STORE
101 throw std::runtime_error(strerror(errno));
107#ifdef PROVSQL_INPROCESS_STORE
110 throw std::runtime_error(
"ProvSQL: out of memory mapping region");
113 throw std::runtime_error(strerror(errno));
114 if(
static_cast<std::size_t
>(r) <
length)
115 memset(
static_cast<char *
>(
base_) + r, 0,
length -
static_cast<std::size_t
>(r));
119 if(
base_ == MAP_FAILED)
120 throw std::runtime_error(strerror(errno));
127#ifdef PROVSQL_INPROCESS_STORE
129 void *p = realloc(
base_, new_length);
131 throw std::runtime_error(
"ProvSQL: out of memory growing region");
137 throw std::runtime_error(strerror(errno));
139 base_ = ::mmap(
nullptr, new_length, PROT_READ | (
read_only_ ? 0 : PROT_WRITE),
141 if(
base_ == MAP_FAILED)
142 throw std::runtime_error(strerror(errno));
160#ifdef PROVSQL_INPROCESS_STORE
164 throw std::runtime_error(strerror(errno));
183 throw std::runtime_error(
"ProvSQL mmap: cannot replace a read-only region");
184#ifdef PROVSQL_INPROCESS_STORE
190 throw std::runtime_error(
"ProvSQL: out of memory replacing region");
197 std::string tmp = std::string(path) +
".new";
198 int tfd = open(tmp.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0600);
200 throw std::runtime_error(strerror(errno));
201 const char *p =
static_cast<const char *
>(data);
202 std::size_t left =
length;
204 ssize_t w = write(tfd, p, left);
209 throw std::runtime_error(strerror(e));
211 left -=
static_cast<std::size_t
>(w);
218 throw std::runtime_error(strerror(e));
224 throw std::runtime_error(strerror(errno));
228 fd_ = open(path, O_RDWR);
230 throw std::runtime_error(strerror(errno));
231 base_ = ::mmap(
nullptr,
length, PROT_READ | PROT_WRITE, MAP_SHARED,
fd_, 0);
232 if(
base_ == MAP_FAILED)
233 throw std::runtime_error(strerror(errno));
242#ifdef PROVSQL_INPROCESS_STORE
244 throw std::runtime_error(strerror(errno));
253#ifdef PROVSQL_INPROCESS_STORE
271#ifndef PROVSQL_INPROCESS_STORE
275 std::string dir(path);
276 auto slash = dir.rfind(
'/');
277 dir = (slash == std::string::npos) ?
"." : dir.substr(0, slash);
278 int dfd = open(dir.c_str(), O_RDONLY);
static int provsql_fdatasync(int fd)
Push a file's dirty data pages to stable storage.
void close()
Write back (if writable) and release the region and file.
std::size_t openFile(const char *filename, bool read_only)
Open (creating if absent) the backing file.
void map(std::size_t length)
Establish the initial region of length bytes over the file.
void remap(std::size_t new_length)
Grow the region to new_length, preserving existing content.
bool read_only_
Opened read-only (no write-back).
MappedRegion(const MappedRegion &)=delete
std::size_t length() const
std::size_t length_
Current region length in bytes.
int fd_
Backing file descriptor.
void * base_
Base of the mapped region / heap buffer.
void sync()
Flush the region to the backing file (no-op when read-only).
static void syncDirectoryOf(const char *path)
Force the directory entry of path to disk, so the rename that created it survives a crash of the mach...
MappedRegion & operator=(const MappedRegion &)=delete
void replaceContents(const char *path, const void *data, std::size_t length)
Replace the backing file, atomically, with length bytes of data, and remap onto the result.
void resizeFile(std::size_t length)
Set the backing file's size.
void flush()
Force the backing file's contents to stable storage.
Build-configuration switches shared across the C and C++ sources.