33 #include <boost/filesystem.hpp>
34 #include <boost/lexical_cast.hpp>
35 #include <boost/system/error_code.hpp>
51 namespace File_Namespace {
65 FileMgr::FileMgr(
const int32_t deviceId,
67 const std::pair<const int32_t, const int> fileMgrKey,
68 const int32_t maxRollbackEpochs,
69 const size_t num_reader_threads,
71 const size_t defaultPageSize)
72 : AbstractBufferMgr(deviceId)
74 , fileMgrKey_(fileMgrKey)
75 , maxRollbackEpochs_(maxRollbackEpochs)
76 , defaultPageSize_(defaultPageSize)
78 init(num_reader_threads, epoch);
82 FileMgr::FileMgr(
const int32_t deviceId,
84 const std::pair<const int32_t, const int32_t> fileMgrKey,
85 const size_t defaultPageSize,
86 const bool runCoreInit)
87 : AbstractBufferMgr(deviceId)
89 , fileMgrKey_(fileMgrKey)
90 , maxRollbackEpochs_(-1)
91 , defaultPageSize_(defaultPageSize)
93 const std::string fileMgrDirPrefix(
"table");
94 const std::string FileMgrDirDelim(
"_");
106 : AbstractBufferMgr(0)
109 , maxRollbackEpochs_(-1)
110 , fileMgrBasePath_(basePath)
111 , defaultPageSize_(defaultPageSize)
124 delete chunkIt->second;
126 for (
auto file_info :
files_) {
143 const std::string fileMgrDirPrefix(
"table");
144 const std::string FileMgrDirDelim(
"_");
149 if (boost::filesystem::exists(path)) {
150 if (!boost::filesystem::is_directory(path)) {
152 <<
"' for table data is not a directory.";
162 const boost::filesystem::directory_iterator& fileIterator) {
165 fileMetadata.
file_path = fileIterator->path().string();
166 if (!boost::filesystem::is_regular_file(fileIterator->status())) {
171 std::string extension(fileIterator->path().extension().string());
173 std::string fileStem(fileIterator->path().stem().string());
175 if (fileStem.size() > 0 && fileStem.back() ==
'.') {
176 fileStem = fileStem.substr(0, fileStem.size() - 1);
178 size_t dotPos = fileStem.find_last_of(
".");
179 if (dotPos == std::string::npos) {
180 LOG(
FATAL) <<
"File `" << fileIterator->path()
181 <<
"` does not carry page size information in the filename.";
184 fileMetadata.
file_id = boost::lexical_cast<
int>(fileStem.substr(0, dotPos));
186 boost::lexical_cast<
size_t>(fileStem.substr(dotPos + 1, fileStem.size()));
196 void FileMgr::init(
const size_t num_reader_threads,
const int32_t epochOverride) {
201 if (epochOverride != -1) {
206 boost::filesystem::directory_iterator
208 int32_t maxFileId = -1;
209 int32_t fileCount = 0;
210 int32_t threadCount = std::thread::hardware_concurrency();
211 std::vector<HeaderInfo> headerVec;
212 std::vector<std::future<std::vector<HeaderInfo>>> file_futures;
214 for (boost::filesystem::directory_iterator fileIt(path); fileIt != endItr; ++fileIt) {
217 maxFileId = std::max(maxFileId, fileMetadata.
file_id);
218 file_futures.emplace_back(std::async(std::launch::async, [fileMetadata,
this] {
219 std::vector<HeaderInfo> tempHeaderVec;
225 return tempHeaderVec;
228 if (fileCount % threadCount == 0) {
234 if (file_futures.size() > 0) {
237 int64_t queue_time_ms =
timer_stop(clock_begin);
239 LOG(
INFO) <<
"Completed Reading table's file metadata, Elapsed time : "
255 VLOG(4) <<
"Number of Headers in Vector: " << headerVec.size();
256 if (headerVec.size() > 0) {
257 ChunkKey lastChunkKey = headerVec.begin()->chunkKey;
258 auto startIt = headerVec.begin();
260 for (
auto headerIt = headerVec.begin() + 1; headerIt != headerVec.end();
262 if (headerIt->chunkKey != lastChunkKey) {
264 new FileBuffer(
this, lastChunkKey, startIt, headerIt);
265 lastChunkKey = headerIt->chunkKey;
271 new FileBuffer(
this, lastChunkKey, startIt, headerVec.end());
284 if (!boost::filesystem::create_directory(path)) {
285 LOG(
FATAL) <<
"Could not create data directory: " << path;
288 if (epochOverride != -1) {
304 size_t num_hardware_based_threads =
305 std::thread::hardware_concurrency();
307 if (num_reader_threads == 0) {
310 if (num_reader_threads > num_hardware_based_threads) {
325 if (boost::filesystem::exists(path)) {
326 if (!boost::filesystem::is_directory(path)) {
328 <<
"' for table data is not a directory.";
333 boost::filesystem::directory_iterator
335 for (boost::filesystem::directory_iterator fileIt(path); fileIt != endItr;
348 UNREACHABLE() <<
"Found file with unexpected page size. Page size: "
350 <<
", file path: " << file_metadata.
file_path;
361 for (
const auto& file_info :
files_) {
365 file_info->pageSize * file_info->numPages;
369 file_info->freePages.size();
383 UNREACHABLE() <<
"Found file with unexpected page size. Page size: "
384 << file_info->pageSize;
388 return storage_stats;
392 std::vector<std::future<std::vector<HeaderInfo>>>& file_futures,
393 std::vector<HeaderInfo>& headerVec) {
394 for (
auto& file_future : file_futures) {
398 for (
auto& file_future : file_futures) {
399 auto tempHeaderVec = file_future.get();
400 headerVec.insert(headerVec.end(), tempHeaderVec.begin(), tempHeaderVec.end());
402 file_futures.clear();
406 const int32_t epochOverride) {
407 int32_t converted_data_epoch = 0;
408 boost::filesystem::path path(dataPathToConvertFrom);
409 if (boost::filesystem::exists(path)) {
410 if (!boost::filesystem::is_directory(path)) {
411 LOG(
FATAL) <<
"Specified path `" << path <<
"` is not a directory.";
415 if (epochOverride != -1) {
419 boost::filesystem::directory_iterator
421 int32_t maxFileId = -1;
422 int32_t fileCount = 0;
423 int32_t threadCount = std::thread::hardware_concurrency();
424 std::vector<HeaderInfo> headerVec;
425 std::vector<std::future<std::vector<HeaderInfo>>> file_futures;
426 for (boost::filesystem::directory_iterator fileIt(path); fileIt != endItr; ++fileIt) {
429 maxFileId = std::max(maxFileId, fileMetadata.
file_id);
430 file_futures.emplace_back(std::async(std::launch::async, [fileMetadata,
this] {
431 std::vector<HeaderInfo> tempHeaderVec;
437 return tempHeaderVec;
440 if (fileCount % threadCount) {
446 if (file_futures.size() > 0) {
461 if (headerVec.size() > 0) {
462 ChunkKey lastChunkKey = headerVec.begin()->chunkKey;
463 auto startIt = headerVec.begin();
465 for (
auto headerIt = headerVec.begin() + 1; headerIt != headerVec.end();
467 if (headerIt->chunkKey != lastChunkKey) {
481 for (
size_t pageNum = 0; pageNum < totalNumPages; pageNum++) {
487 multiPage.
push(destPage, converted_data_epoch);
491 srcPage, c_fm_, destPage, reservedHeaderSize, srcBuf->
pageDataSize(), 0);
492 destBuf->
writeHeader(destPage, pageNum, converted_data_epoch,
false);
494 lastChunkKey = headerIt->chunkKey;
512 for (
size_t pageNum = 0; pageNum < totalNumPages; pageNum++) {
518 multiPage.
push(destPage, converted_data_epoch);
522 destBuf->
writeHeader(destPage, pageNum, converted_data_epoch,
false);
527 if (!boost::filesystem::create_directory(path)) {
528 LOG(
FATAL) <<
"Specified path does not exist: " << path;
535 for (
auto file_info :
files_) {
538 file_info->f =
nullptr;
559 const size_t reservedHeaderSize,
560 const size_t numBytes,
561 const size_t offset) {
565 int8_t* buffer =
reinterpret_cast<int8_t*
>(
checked_malloc(numBytes));
567 size_t bytesRead = srcFileInfo->
read(
569 CHECK(bytesRead == numBytes);
570 size_t bytesWritten = destFileInfo->
write(
574 CHECK(bytesWritten == numBytes);
580 if (boost::filesystem::exists(epochFilePath)) {
581 LOG(
FATAL) <<
"Epoch file `" << epochFilePath <<
"` already exists";
591 if (!boost::filesystem::exists(epochFilePath)) {
595 if (!boost::filesystem::is_regular_file(epochFilePath)) {
596 LOG(
FATAL) <<
"Epoch file `" << epochFilePath <<
"` is not a regular file";
599 LOG(
FATAL) <<
"Epoch file `" << epochFilePath
600 <<
"` is not sized properly (current size: "
603 FILE* legacyEpochFile =
open(epochFilePath);
605 read(legacyEpochFile, 0,
sizeof(int32_t), (int8_t*)&epoch);
612 if (!boost::filesystem::exists(epochFilePath)) {
613 LOG(
FATAL) <<
"Epoch file `" << epochFilePath <<
"` does not exist";
615 if (!boost::filesystem::is_regular_file(epochFilePath)) {
616 LOG(
FATAL) <<
"Epoch file `" << epochFilePath <<
"` is not a regular file";
619 LOG(
FATAL) <<
"Epoch file `" << epochFilePath
620 <<
"` is not sized properly (current size: "
633 LOG(
FATAL) <<
"Could not flush epoch file to disk";
641 LOG(
FATAL) <<
"Could not sync epoch file to disk";
648 chunkIt->second->freePagesBeforeEpoch(minRollbackEpoch);
654 const int32_t minRollbackEpoch =
659 if (shouldCheckpoint) {
668 <<
" epoch: " <<
epoch();
671 if (chunkIt->second->isDirty()) {
672 chunkIt->second->writeMetadata(
epoch());
673 chunkIt->second->clearDirtyBits();
676 chunkIndexWriteLock.unlock();
679 for (
auto fileIt =
files_.begin(); fileIt !=
files_.end(); ++fileIt) {
680 int32_t status = (*fileIt)->syncToDisk();
682 LOG(
FATAL) <<
"Could not sync file to disk";
698 const size_t pageSize,
699 const size_t numBytes) {
708 const size_t pageSize,
709 const size_t numBytes) {
710 size_t actualPageSize = pageSize;
711 if (actualPageSize == 0) {
737 chunkIndexWriteLock.unlock();
740 chunkIt->second->freePages();
743 delete chunkIt->second;
754 std::search(chunkIt->first.begin(),
755 chunkIt->first.begin() + keyPrefix.size(),
757 keyPrefix.end()) != chunkIt->first.begin() + keyPrefix.size()) {
759 chunkIt->second->freePages();
762 delete chunkIt->second;
771 <<
"Chunk does not exist for key: " <<
show_chunk(key);
772 return chunkIt->second;
777 const size_t numBytes) {
782 <<
"Aborting attempt to fetch a chunk marked dirty. Chunk inconsistency for key: "
790 chunkIndexReadLock.unlock();
795 if (numBytes > 0 && numBytes > chunk->
size()) {
797 << chunk->
size() <<
") than number of bytes requested (" << numBytes
801 chunk->
copyTo(destBuffer, numBytes);
806 const size_t numBytes) {
814 chunk = chunkIt->second;
816 chunkIndexWriteLock.unlock();
817 size_t oldChunkSize = chunk->
size();
820 size_t newChunkSize = numBytes == 0 ? srcBuffer->
size() : numBytes;
825 LOG(
FATAL) <<
"Aborting attempt to write a chunk marked dirty. Chunk inconsistency "
835 if (0 == numBytes && !chunk->
isDirty()) {
846 CHECK_LT(oldChunkSize, newChunkSize);
848 newChunkSize - oldChunkSize,
852 UNREACHABLE() <<
"putBuffer() expects a buffer marked is_updated or is_appended";
863 LOG(
FATAL) <<
"Operation not supported";
868 LOG(
FATAL) <<
"Operation not supported";
874 auto candidateFiles =
fileIndex_.equal_range(pageSize);
875 int32_t pageNum = -1;
876 for (
auto fileIt = candidateFiles.first; fileIt != candidateFiles.second; ++fileIt) {
891 CHECK(pageNum != -1);
897 std::vector<Page>& pages,
898 const bool isMetadata) {
902 auto candidateFiles =
fileIndex_.equal_range(pageSize);
903 size_t numPagesNeeded = numPagesRequested;
904 for (
auto fileIt = candidateFiles.first; fileIt != candidateFiles.second; ++fileIt) {
910 pages.emplace_back(fileInfo->
fileId, pageNum);
913 }
while (pageNum != -1 && numPagesNeeded > 0);
914 if (numPagesNeeded == 0) {
918 while (numPagesNeeded > 0) {
929 pages.emplace_back(fileInfo->
fileId, pageNum);
932 }
while (pageNum != -1 && numPagesNeeded > 0);
933 if (numPagesNeeded == 0) {
937 CHECK(pages.size() == numPagesRequested);
942 const size_t pageSize,
943 const size_t numPages,
944 std::vector<HeaderInfo>& headerVec) {
945 FILE*
f =
open(path);
947 this, fileId, f, pageSize, numPages,
false);
951 if (fileId >= static_cast<int32_t>(
files_.size())) {
952 files_.resize(fileId + 1);
955 fileIndex_.insert(std::pair<size_t, int32_t>(pageSize, fileId));
961 if (pageSize == 0 || numPages == 0) {
962 LOG(
FATAL) <<
"File creation failed: pageSize and numPages must be greater than 0.";
976 new FileInfo(
this, fileId, f, pageSize, numPages,
true);
982 fileIndex_.insert(std::pair<size_t, int32_t>(pageSize, fileId));
989 CHECK(fileId >= 0 && static_cast<size_t>(fileId) <
files_.size());
995 mapd_unique_lock<mapd_shared_mutex> chunkIndexWriteLock(
1003 std::search(chunkIt->first.begin(),
1004 chunkIt->first.begin() + keyPrefix.size(),
1006 keyPrefix.end()) != chunkIt->first.begin() + keyPrefix.size()) {
1007 if (chunkIt->second->hasEncoder()) {
1008 auto chunk_metadata = std::make_shared<ChunkMetadata>();
1009 chunkIt->second->encoder_->getMetadata(chunk_metadata);
1010 chunkMetadataVec.emplace_back(chunkIt->first, chunk_metadata);
1017 size_t num_used_pages = 0;
1019 for (
const auto file :
files_) {
1020 num_used_pages += (file->numPages - file->freePages.size());
1022 return num_used_pages;
1026 size_t num_used_metadata_pages = 0;
1029 num_used_metadata_pages += chunkIt.second->numMetadataPages();
1031 return num_used_metadata_pages;
1038 return chunkIt->second->numMetadataPages();
1040 throw std::runtime_error(
"Chunk was not found.");
1056 LOG(
FATAL) <<
"DB forward compatibility is not supported. Version of OmniSci "
1057 "software used is older than the version of DB being read: "
1069 const std::string versionFilePath(
fileMgrBasePath_ +
"/" + versionFileName);
1070 if (!boost::filesystem::exists(versionFilePath)) {
1073 if (!boost::filesystem::is_regular_file(versionFilePath)) {
1079 FILE* versionFile =
open(versionFilePath);
1081 read(versionFile, 0,
sizeof(int32_t), (int8_t*)&version);
1088 const std::string versionFilePath(
fileMgrBasePath_ +
"/" + versionFileName);
1090 if (boost::filesystem::exists(versionFilePath)) {
1092 LOG(
INFO) <<
"Storage version file `" << versionFilePath
1093 <<
"` already exists, its current version is " << oldVersion;
1094 versionFile =
open(versionFilePath);
1096 versionFile =
create(versionFilePath,
sizeof(int32_t));
1098 write(versionFile, 0,
sizeof(int32_t), (int8_t*)&version);
1099 int32_t status = fflush(versionFile);
1101 LOG(
FATAL) <<
"Could not flush version file " << versionFilePath <<
" to disk";
1109 LOG(
FATAL) <<
"Could not sync version file " << versionFilePath <<
" to disk";
1116 LOG(
INFO) <<
"Migrating file format version from 0 to 1 for `" << versionFilePath;
1121 int32_t migrationCompleteVersion = 1;
1132 <<
"Table storage forward compatibility is not supported. Version of OmniSci "
1133 "software used is older than the version of table being read: "
1167 std::stringstream error_message;
1168 error_message <<
"Cannot set epoch for table (" <<
fileMgrKey_.first <<
","
1169 <<
fileMgrKey_.second <<
") lower than the minimum rollback epoch ("
1171 throw std::runtime_error(error_message.str());
1187 uint64_t total_size = 0;
1188 for (
const auto& file :
files_) {
1189 total_size += file->size();
virtual std::vector< MultiPage > getMultiPage() const
Returns vector of MultiPages in the FileBuffer.
int32_t openAndReadLegacyEpochFile(const std::string &epochFileName)
size_t getNumUsedPages() const
void createTopLevelMetadata()
int32_t readVersionFromDisk(const std::string &versionFileName) const
#define METADATA_PAGE_SIZE
std::vector< int > ChunkKey
FileMetadata getMetadataForFile(const boost::filesystem::directory_iterator &fileIterator)
AbstractBuffer * alloc(const size_t numBytes) override
uint64_t total_data_page_count
std::string getBasePath() const
mapd_shared_mutex mutex_free_page_
void createEpochFile(const std::string &epochFileName)
Page requestFreePage(size_t pagesize, const bool isMetadata)
size_t getNumUsedMetadataPagesForChunkKey(const ChunkKey &chunkKey) const
void syncEncoder(const AbstractBuffer *src_buffer)
FileBuffer * createBuffer(const ChunkKey &key, size_t pageSize=0, const size_t numBytes=0) override
Creates a chunk with the specified key and page size.
uint64_t metadata_file_count
A logical page (Page) belongs to a file on disk.
uint64_t getTotalFileSize() const
virtual int8_t * getMemoryPtr()=0
void free(AbstractBuffer *buffer) override
virtual MemoryLevel getType() const =0
void write(int8_t *src, const size_t numBytes, const size_t offset=0, const MemoryLevel srcMemoryLevel=CPU_LEVEL, const int32_t deviceId=-1) override
Writes the contents of source (src) into new versions of the affected logical pages.
void copyPage(Page &srcPage, FileMgr *destFileMgr, Page &destPage, const size_t reservedHeaderSize, const size_t numBytes, const size_t offset)
void migrateToLatestFileMgrVersion()
void rollOffOldData(const int32_t epochCeiling, const bool shouldCheckpoint)
DEVICE void sort(ARGS &&...args)
void init(const size_t num_reader_threads, const int32_t epochOverride)
TypeR::rep timer_stop(Type clock_begin)
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
std::vector< MultiPage > multiPages_
bool getDBConvert() const
static int64_t min_allowable_epoch()
std::string getFileMgrBasePath() const
std::mutex getPageMutex_
pointer to DB level metadata
std::optional< uint64_t > total_free_data_page_count
Represents/provides access to contiguous data stored in the file system.
void checkpoint() override
Fsyncs data files, writes out epoch and fsyncs that.
int32_t getDBVersion() const
std::string fileMgrBasePath_
bool headerCompare(const HeaderInfo &firstElem, const HeaderInfo &secondElem)
FILE * create(const std::string &basePath, const int fileId, const size_t pageSize, const size_t numPages)
void fetchBuffer(const ChunkKey &key, AbstractBuffer *destBuffer, const size_t numBytes) override
std::string show_chunk(const ChunkKey &key)
FileMgr(const int32_t deviceId, GlobalFileMgr *gfm, const std::pair< const int32_t, const int32_t > fileMgrKey, const int32_t max_rollback_epochs=-1, const size_t num_reader_threads=0, const int32_t epoch=-1, const size_t defaultPageSize=DEFAULT_PAGE_SIZE)
Constructor.
const int32_t latestFileMgrVersion_
size_t write(const size_t offset, const size_t size, int8_t *buf)
std::vector< FileInfo * > files_
void writeAndSyncVersionToDisk(const std::string &versionFileName, const int32_t version)
size_t read(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Reads the specified number of bytes from the offset position in file f into buf.
constexpr char LEGACY_EPOCH_FILENAME[]
void removeTableRelatedDS(const int32_t db_id, const int32_t table_id) override
void init(LogOptions const &log_opts)
void processFileFutures(std::vector< std::future< std::vector< HeaderInfo >>> &file_futures, std::vector< HeaderInfo > &headerVec)
StorageStats getStorageStats()
void * checked_malloc(const size_t size)
std::optional< uint64_t > total_free_metadata_page_count
std::pair< const int32_t, const int32_t > fileMgrKey_
Global FileMgr.
int32_t getDBVersion() const
Index for looking up chunks.
size_t pageSize() const override
Returns the size in bytes of each page in the FileBuffer.
#define MAX_FILE_N_METADATA_PAGES
ChunkKeyToChunkMap chunkIndex_
PageSizeFileMMap fileIndex_
A vector of files accessible via a file identifier.
constexpr char EPOCH_FILENAME[]
uint64_t total_metadata_page_count
FILE * getFileForFileId(const int32_t fileId)
Returns FILE pointer associated with requested fileId.
std::vector< std::pair< FileInfo *, int32_t > > free_pages_
An AbstractBuffer is a unit of data management for a data manager.
size_t getNumUsedMetadataPages() const
size_t num_reader_threads_
Maps page sizes to FileInfo objects.
bool isBufferOnDevice(const ChunkKey &key) override
FileInfo * openExistingFile(const std::string &path, const int32_t fileId, const size_t pageSize, const size_t numPages, std::vector< HeaderInfo > &headerVec)
void writeAndSyncEpochToDisk()
size_t pageNum
unique identifier of the owning file
void append(int8_t *src, const size_t numBytes, const MemoryLevel srcMemoryLevel=CPU_LEVEL, const int32_t deviceId=-1) override
void deleteBuffersWithPrefix(const ChunkKey &keyPrefix, const bool purge=true) override
size_t fileSize(FILE *f)
Returns the size of the specified file.
void getChunkMetadataVecForKeyPrefix(ChunkMetadataVector &chunkMetadataVec, const ChunkKey &keyPrefix) override
FileInfo * getFileInfoForFileId(const int32_t fileId)
size_t defaultPageSize_
number of threads used when loading data
FileBuffer * createBufferUnlocked(const ChunkKey &key, size_t pageSize=0, const size_t numBytes=0)
void writeHeader(Page &page, const int32_t pageId, const int32_t epoch, const bool writeMetadata=false)
Write header writes header at top of page in format.
int32_t maxRollbackEpochs_
virtual size_t reservedHeaderSize() const
uint64_t total_metadata_file_size
void openExistingFile(std::vector< HeaderInfo > &headerVec, const int32_t fileMgrEpoch)
void migrateEpochFileV0()
void push(const Page &page, const int epoch)
Pushes a new page with epoch value.
void openAndReadEpochFile(const std::string &epochFileName)
size_t read(const size_t offset, const size_t size, int8_t *buf)
bool epochIsCheckpointed_
constexpr int32_t INVALID_VERSION
uint64_t total_data_file_size
static size_t byte_size()
int32_t epoch()
Returns current value of epoch - should be one greater than recorded at last checkpoint.
~FileMgr() override
Destructor.
bool getDBConvert() const
void freePagesBeforeEpoch(const int32_t minRollbackEpoch)
void setSize(const size_t size)
void free_page(std::pair< FileInfo *, int32_t > &&page)
void copyTo(AbstractBuffer *destination_buffer, const size_t num_bytes=0)
void closeRemovePhysical()
AbstractBufferMgr * getFileMgr(const int32_t db_id, const int32_t tb_id)
mapd_shared_lock< mapd_shared_mutex > read_lock
FILE * open(int fileId)
Opens/creates the file with the given id; returns NULL on error.
FileInfo * createFile(const size_t pageSize, const size_t numPages)
Adds a file to the file manager repository.
size_t write(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Writes the specified number of bytes to the offset position in file f from buf.
FileBuffer * getBuffer(const ChunkKey &key, const size_t numBytes=0) override
Returns the a pointer to the chunk with the specified key.
constexpr char FILE_MGR_VERSION_FILENAME[]
constexpr char DB_META_FILENAME[]
void close(FILE *f)
Closes the file pointed to by the FILE pointer.
void setEpoch(const int32_t newEpoch)
bool coreInit()
Determines file path, and if exists, runs file migration and opens and reads epoch file...
void requestFreePages(size_t npages, size_t pagesize, std::vector< Page > &pages, const bool isMetadata)
Obtains free pages – creates new files if necessary – of the requested size.
mapd_unique_lock< mapd_shared_mutex > write_lock
void renameForDelete(const std::string directoryName)
Renames a directory to DELETE_ME_<EPOCH>_<oldname>.
mapd_shared_mutex chunkIndexMutex_
virtual size_t pageDataSize() const
Returns the size in bytes of the data portion of each page in the FileBuffer.
mapd_shared_mutex files_rw_mutex_
The MultiPage stores versions of the same logical page in a deque.
A selection of helper methods for File I/O.
Epoch epoch_
the index of the next file id
FileBuffer * putBuffer(const ChunkKey &key, AbstractBuffer *d, const size_t numBytes=0) override
Puts the contents of d into the Chunk with the given key.
int32_t lastCheckpointedEpoch()
Returns value of epoch at last checkpoint.
size_t file_size(const int fd)