mirror of
https://github.com/Tencent/MMKV.git
synced 2026-10-16 20:21:12 +08:00
add mayfly fd for Win32/POSIX
This commit is contained in:
+1
-1
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user