add mayfly fd for Win32/POSIX

This commit is contained in:
guoling
2025-04-18 21:52:05 +08:00
parent 608d775bf6
commit f0e80ad484
5 changed files with 116 additions and 37 deletions
+1 -1
View File
@@ -97,7 +97,7 @@ constexpr auto MMKV_VERSION = "v2.1.0";
constexpr auto MMKV_PATH_SLASH = L"\\";
# define MMKV_PATH_FORMAT "%ls"
using MMKVFileHandle_t = HANDLE;
constexpr MMKVFileHandle_t MMKVFileHandleInvalidValue = INVALID_HANDLE_VALUE;
#define MMKVFileHandleInvalidValue INVALID_HANDLE_VALUE
using MMKVPath_t = std::wstring;
extern MMKVPath_t string2MMKVPath_t(const std::string &str);
extern std::string MMKVPath_t2String(const MMKVPath_t &str);
+33 -13
View File
@@ -43,7 +43,7 @@ namespace fs = std::filesystem;
namespace mmkv {
extern bool getFileSize(int fd, size_t &size);
static bool getFileSize(const char *path, size_t &size);
# ifdef MMKV_ANDROID
extern size_t ASharedMemory_getSize(int fd);
@@ -122,7 +122,11 @@ size_t File::getActualFileSize() const {
}
# endif
size_t size = 0;
mmkv::getFileSize(m_fd, size);
if (isFileValid()) {
mmkv::getFileSize(m_fd, size);
} else {
mmkv::getFileSize(m_path.c_str(), size);
}
return size;
}
@@ -140,18 +144,11 @@ void MemoryFile::cleanMayflyFD() {
}
size_t MemoryFile::getActualFileSize() {
if (m_isMayflyFD) {
openIfNeeded();
}
if (!m_diskFile.isFileValid()) {
if (!m_isMayflyFD && !m_diskFile.isFileValid()) {
return 0;
}
auto size = m_diskFile.getActualFileSize();
cleanMayflyFD();
return size;
return m_diskFile.getActualFileSize();
}
MMKVFileHandle_t MemoryFile::getFd() {
@@ -432,6 +429,7 @@ bool zeroFillFile(int fd, size_t startPos, size_t size) {
}
#ifndef MMKV_APPLE
bool getFileSize(int fd, size_t &size) {
struct stat st = {};
if (fstat(fd, &st) != -1) {
@@ -440,7 +438,18 @@ bool getFileSize(int fd, size_t &size) {
}
return false;
}
#else
bool getFileSize(const char *path, size_t &size) {
struct stat st = {};
if (stat(path, &st) != -1) {
size = (size_t) st.st_size;
return true;
}
return false;
}
#else // !MMKV_APPLE
// avoid using so-called privacy API
bool getFileSize(int fd, size_t &size) {
auto cur = lseek(fd, 0, SEEK_CUR);
@@ -456,7 +465,18 @@ bool getFileSize(int fd, size_t &size) {
lseek(fd, cur, SEEK_SET);
return true;
}
#endif
bool getFileSize(const char *path, size_t &size) {
auto fd = open(path, O_RDONLY);
if (fd >= 0) {
auto ret = getFileSize(fd, size);
close(fd);
return ret;
}
return false;
}
#endif // !MMKV_APPLE
size_t getPageSize() {
return static_cast<size_t>(getpagesize());
Regular → Executable
+4 -2
View File
@@ -163,7 +163,7 @@ public:
#ifndef MMKV_WIN32
bool isFileValid() { return (m_isMayflyFD || m_diskFile.isFileValid()) && m_size > 0 && m_ptr; }
#else
bool isFileValid() { return (m_isMayflyFD || m_diskFile.isFileValid()) && m_size > 0 && m_fileMapping && m_ptr; }
bool isFileValid() { return (m_isMayflyFD || (m_diskFile.isFileValid() && m_fileMapping)) && m_size > 0 && m_ptr; }
#endif
// just forbid it for possibly misuse
@@ -179,7 +179,9 @@ extern MMBuffer *readWholeFile(const MMKVPath_t &path);
extern bool zeroFillFile(MMKVFileHandle_t fd, size_t startPos, size_t size);
extern size_t getPageSize();
extern MMKVPath_t absolutePath(const MMKVPath_t &path);
#ifndef MMKV_WIN32
extern bool getFileSize(int fd, size_t &size);
#endif
extern bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath);
// copy file by potentially renaming target file, might change file inode
-2
View File
@@ -48,8 +48,6 @@ typedef int (*renameat2_t)(int old_dir_fd, const char* old_path, int new_dir_fd,
namespace mmkv {
extern bool getFileSize(int fd, size_t &size);
bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
bool renamed = false;
+78 -19
View File
@@ -37,6 +37,7 @@ namespace fs = std::filesystem;
namespace mmkv {
static bool getFileSize(MMKVFileHandle_t fd, size_t &size);
static bool getFileSize(const wchar_t *filename, size_t &size);
static bool ftruncate(MMKVFileHandle_t file, size_t size);
File::File(MMKVPath_t path, OpenFlag flag) : m_path(std::move(path)), m_fd(INVALID_HANDLE_VALUE), m_flag(flag) {
@@ -92,20 +93,28 @@ void File::close() {
size_t File::getActualFileSize() const {
size_t size = 0;
mmkv::getFileSize(m_fd, size);
if (isFileValid()) {
mmkv::getFileSize(m_fd, size);
} else {
mmkv::getFileSize(m_path.c_str(), size);
}
return size;
}
MemoryFile::MemoryFile(MMKVPath_t path, size_t expectedCapacity, bool readOnly)
MemoryFile::MemoryFile(MMKVPath_t path, size_t expectedCapacity, bool readOnly, bool mayflyFD)
: m_diskFile(std::move(path), readOnly ? OpenFlag::ReadOnly : (OpenFlag::ReadWrite | OpenFlag::Create))
, m_fileMapping(nullptr)
, m_ptr(nullptr)
, m_size(0)
, m_readOnly(readOnly) {
, m_readOnly(readOnly)
, m_isMayflyFD(mayflyFD) {
reloadFromFile(expectedCapacity);
}
bool MemoryFile::truncate(size_t size) {
if (m_isMayflyFD) {
openIfNeeded();
}
if (!m_diskFile.isFileValid()) {
return false;
}
@@ -143,7 +152,7 @@ bool MemoryFile::truncate(size_t size) {
MMKVError("fail to truncate [%ls] to size %zu", m_diskFile.m_path.c_str(), m_size);
m_size = oldSize;
if (needMMapOnFailure) {
mmap();
mmapOrCleanup();
}
return false;
}
@@ -152,17 +161,13 @@ bool MemoryFile::truncate(size_t size) {
MMKVError("fail to zeroFile [%ls] to size %zu", m_diskFile.m_path.c_str(), m_size);
m_size = oldSize;
if (needMMapOnFailure) {
mmap();
mmapOrCleanup();
}
return false;
}
}
auto ret = mmap();
if (!ret) {
doCleanMemoryCache(true);
}
return ret;
return mmapOrCleanup();
}
bool MemoryFile::msync(SyncFlag syncFlag) {
@@ -172,11 +177,13 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
}
if (m_ptr) {
if (FlushViewOfFile(m_ptr, m_size)) {
if (syncFlag == MMKV_SYNC) {
if (!FlushFileBuffers(m_diskFile.getFd())) {
if (syncFlag == MMKV_SYNC && openIfNeeded()) {
auto ret = FlushFileBuffers(m_diskFile.getFd());
if (!ret) {
MMKVError("fail to FlushFileBuffers [%ls]:%d", m_diskFile.m_path.c_str(), GetLastError());
return false;
}
cleanMayflyFD();
return ret;
}
return true;
}
@@ -186,7 +193,7 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
return false;
}
bool MemoryFile::mmap() {
bool MemoryFile::mmapOrCleanup() {
auto mode = m_readOnly ? PAGE_READONLY : PAGE_READWRITE;
m_fileMapping = CreateFileMapping(m_diskFile.getFd(), nullptr, mode, 0, 0, nullptr);
if (!m_fileMapping) {
@@ -197,9 +204,13 @@ bool MemoryFile::mmap() {
m_ptr = (char*)MapViewOfFile(m_fileMapping, viewMode, 0, 0, 0);
if (!m_ptr) {
MMKVError("fail to mmap [%ls], mode %x, %d", m_diskFile.m_path.c_str(), viewMode, GetLastError());
doCleanMemoryCache(true);
return false;
}
MMKVInfo("mmap to address [%p], [%ls]", m_ptr, m_diskFile.m_path.c_str());
cleanMayflyFD();
return true;
}
}
@@ -210,8 +221,7 @@ void MemoryFile::reloadFromFile(size_t expectedCapacity) {
assert(0);
clearMemoryCache();
}
m_diskFile.open();
if (m_diskFile.isFileValid()) {
if (openIfNeeded()) {
FileLock fileLock(m_diskFile.getFd());
InterProcessLock lock(&fileLock, ExclusiveLockType);
SCOPED_LOCK(&lock);
@@ -223,10 +233,16 @@ void MemoryFile::reloadFromFile(size_t expectedCapacity) {
size_t roundSize = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;;
roundSize = std::max<size_t>(expectedSize, roundSize);
truncate(roundSize);
// TODO: or should we dup() ?
if (m_isMayflyFD) {
fileLock.destroyLock();
}
} else {
auto ret = mmap();
if (!ret) {
doCleanMemoryCache(true);
mmapOrCleanup();
if (m_isMayflyFD) {
fileLock.destroyLock();
}
}
}
@@ -244,6 +260,40 @@ void MemoryFile::doCleanMemoryCache(bool forceClean) {
m_diskFile.close();
}
bool MemoryFile::openIfNeeded() {
if (!m_diskFile.isFileValid()) {
return m_diskFile.open();
}
return true;
}
void MemoryFile::cleanMayflyFD() {
if (m_isMayflyFD) {
if (m_diskFile.isFileValid()) {
m_diskFile.close();
}
if (m_fileMapping) {
CloseHandle(m_fileMapping);
m_fileMapping = nullptr;
}
}
}
size_t MemoryFile::getActualFileSize() {
if (!m_isMayflyFD && !m_diskFile.isFileValid()) {
return 0;
}
return m_diskFile.getActualFileSize();
}
MMKVFileHandle_t MemoryFile::getFd() {
if (m_isMayflyFD) {
openIfNeeded();
}
return m_diskFile.getFd();
}
size_t getPageSize() {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
@@ -382,6 +432,15 @@ static bool getFileSize(MMKVFileHandle_t fd, size_t &size) {
return false;
}
bool getFileSize(const wchar_t *filename, size_t &size) {
WIN32_FILE_ATTRIBUTE_DATA fileAttr;
if (GetFileAttributesEx(filename, GetFileExInfoStandard, &fileAttr)) {
size = ((ULONGLONG)fileAttr.nFileSizeHigh << 32) | fileAttr.nFileSizeLow;
return true;
}
return false;
}
static pair<MMKVPath_t, MMKVFileHandle_t> createUniqueTempFile(const wchar_t *prefix) {
wchar_t lpTempPathBuffer[MAX_PATH];
// Gets the temp path env string (no guarantee it's a valid path).