add readonly support

This commit is contained in:
guoling
2024-09-06 19:44:02 +08:00
parent 3624d0ec4d
commit 47d3c0893a
52 changed files with 634 additions and 123 deletions
+22 -11
View File
@@ -43,7 +43,7 @@ File::File(MMKVPath_t path, OpenFlag flag) : m_path(std::move(path)), m_fd(INVAL
static pair<int, int> OpenFlag2NativeFlag(OpenFlag flag) {
int access = 0, create = OPEN_EXISTING;
if (flag & OpenFlag::ReadWrite) {
if ((flag & OpenFlagRWMask) == OpenFlag::ReadWrite) {
access = (GENERIC_READ | GENERIC_WRITE);
} else if (flag & OpenFlag::ReadOnly) {
access |= GENERIC_READ;
@@ -70,10 +70,10 @@ bool File::open() {
m_fd = CreateFile(m_path.c_str(), pair.first, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
pair.second, FILE_ATTRIBUTE_NORMAL, nullptr);
if (!isFileValid()) {
MMKVError("fail to open:[%ls], %d", m_path.c_str(), GetLastError());
MMKVError("fail to open:[%ls], flag %x, error %d", m_path.c_str(), m_flag, GetLastError());
return false;
}
MMKVInfo("open fd[%p], %ls", m_fd, m_path.c_str());
MMKVInfo("open fd[%p], flag %x, %ls", m_fd, m_flag, m_path.c_str());
return true;
}
@@ -94,11 +94,12 @@ size_t File::getActualFileSize() const {
return size;
}
MemoryFile::MemoryFile(MMKVPath_t path, size_t expectedCapacity)
: m_diskFile(std::move(path), OpenFlag::ReadWrite | OpenFlag::Create)
MemoryFile::MemoryFile(MMKVPath_t path, size_t expectedCapacity, bool readOnly)
: m_diskFile(std::move(path), readOnly ? OpenFlag::ReadOnly : (OpenFlag::ReadWrite | OpenFlag::Create))
, m_fileMapping(nullptr)
, m_ptr(nullptr)
, m_size(0) {
, m_size(0)
, m_readOnly(readOnly) {
reloadFromFile(expectedCapacity);
}
@@ -109,6 +110,10 @@ bool MemoryFile::truncate(size_t size) {
if (size == m_size) {
return true;
}
if (m_readOnly) {
// truncate readonly file not allow
return false;
}
auto oldSize = m_size;
m_size = size;
@@ -151,6 +156,10 @@ bool MemoryFile::truncate(size_t size) {
}
bool MemoryFile::msync(SyncFlag syncFlag) {
if (m_readOnly) {
// there's no point in msync() readonly memory
return true;
}
if (m_ptr) {
if (FlushViewOfFile(m_ptr, m_size)) {
if (syncFlag == MMKV_SYNC) {
@@ -168,14 +177,16 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
}
bool MemoryFile::mmap() {
m_fileMapping = CreateFileMapping(m_diskFile.getFd(), nullptr, PAGE_READWRITE, 0, 0, nullptr);
auto mode = m_readOnly ? PAGE_READONLY : PAGE_READWRITE;
m_fileMapping = CreateFileMapping(m_diskFile.getFd(), nullptr, mode, 0, 0, nullptr);
if (!m_fileMapping) {
MMKVError("fail to CreateFileMapping [%ls], %d", m_diskFile.m_path.c_str(), GetLastError());
MMKVError("fail to CreateFileMapping [%ls], mode %x, %d", m_diskFile.m_path.c_str(), mode, GetLastError());
return false;
} else {
m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
auto viewMode = m_readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS;
m_ptr = (char *) MapViewOfFile(m_fileMapping, viewMode, 0, 0, 0);
if (!m_ptr) {
MMKVError("fail to mmap [%ls], %d", m_diskFile.m_path.c_str(), GetLastError());
MMKVError("fail to mmap [%ls], mode %x, %d", m_diskFile.m_path.c_str(), viewMode, GetLastError());
return false;
}
MMKVInfo("mmap to address [%p], [%ls]", m_ptr, m_diskFile.m_path.c_str());
@@ -199,7 +210,7 @@ void MemoryFile::reloadFromFile(size_t expectedCapacity) {
mmkv::getFileSize(m_diskFile.getFd(), m_size);
size_t expectedSize = std::max<size_t>(DEFAULT_MMAP_SIZE, roundUp<size_t>(expectedCapacity, DEFAULT_MMAP_SIZE));
// round up to (n * pagesize)
if (m_size < expectedSize || (m_size % DEFAULT_MMAP_SIZE != 0)) {
if (!m_readOnly && (m_size < expectedSize || (m_size % DEFAULT_MMAP_SIZE != 0))) {
size_t roundSize = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;;
roundSize = std::max<size_t>(expectedSize, roundSize);
truncate(roundSize);