react-native-mmkv 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,23 +41,42 @@ extern int ASharedMemory_create(const char *name, size_t size);
41
41
  extern size_t ASharedMemory_getSize(int fd);
42
42
  extern string ASharedMemory_getName(int fd);
43
43
 
44
- MemoryFile::MemoryFile(const string &path, size_t size, FileType fileType)
45
- : m_name(path), m_fd(-1), m_ptr(nullptr), m_size(0), m_fileType(fileType) {
44
+ File::File(MMKVPath_t path, OpenFlag flag, size_t size, FileType fileType)
45
+ : m_path(std::move(path)), m_fd(-1), m_flag(flag), m_size(0), m_fileType(fileType) {
46
46
  if (m_fileType == MMFILE_TYPE_FILE) {
47
- reloadFromFile();
47
+ open();
48
48
  } else {
49
49
  // round up to (n * pagesize)
50
50
  if (size < DEFAULT_MMAP_SIZE || (size % DEFAULT_MMAP_SIZE != 0)) {
51
51
  size = ((size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;
52
52
  }
53
- auto filename = m_name.c_str();
53
+ auto filename = m_path.c_str();
54
54
  auto ptr = strstr(filename, ASHMEM_NAME_DEF);
55
55
  if (ptr && ptr[sizeof(ASHMEM_NAME_DEF) - 1] == '/') {
56
56
  filename = ptr + sizeof(ASHMEM_NAME_DEF);
57
57
  }
58
58
  m_fd = ASharedMemory_create(filename, size);
59
- if (m_fd >= 0) {
59
+ if (isFileValid()) {
60
60
  m_size = size;
61
+ }
62
+ }
63
+ }
64
+
65
+ File::File(MMKVFileHandle_t ashmemFD)
66
+ : m_path(), m_fd(ashmemFD), m_flag(OpenFlag::ReadWrite), m_size(0), m_fileType(MMFILE_TYPE_ASHMEM) {
67
+ if (isFileValid()) {
68
+ m_path = ASharedMemory_getName(m_fd);
69
+ m_size = ASharedMemory_getSize(m_fd);
70
+ }
71
+ }
72
+
73
+ MemoryFile::MemoryFile(string path, size_t size, FileType fileType)
74
+ : m_diskFile(std::move(path), OpenFlag::ReadWrite | OpenFlag::Create, size, fileType), m_ptr(nullptr), m_size(0), m_fileType(fileType) {
75
+ if (m_fileType == MMFILE_TYPE_FILE) {
76
+ reloadFromFile();
77
+ } else {
78
+ if (m_diskFile.isFileValid()) {
79
+ m_size = m_diskFile.m_size;
61
80
  auto ret = mmap();
62
81
  if (!ret) {
63
82
  doCleanMemoryCache(true);
@@ -67,13 +86,12 @@ MemoryFile::MemoryFile(const string &path, size_t size, FileType fileType)
67
86
  }
68
87
 
69
88
  MemoryFile::MemoryFile(int ashmemFD)
70
- : m_name(""), m_fd(ashmemFD), m_ptr(nullptr), m_size(0), m_fileType(MMFILE_TYPE_ASHMEM) {
71
- if (m_fd < 0) {
72
- MMKVError("fd %d invalid", m_fd);
89
+ : m_diskFile(ashmemFD), m_ptr(nullptr), m_size(0), m_fileType(MMFILE_TYPE_ASHMEM) {
90
+ if (!m_diskFile.isFileValid()) {
91
+ MMKVError("fd %d invalid", ashmemFD);
73
92
  } else {
74
- m_name = ASharedMemory_getName(m_fd);
75
- m_size = ASharedMemory_getSize(m_fd);
76
- MMKVInfo("ashmem name:%s, size:%zu", m_name.c_str(), m_size);
93
+ m_size = m_diskFile.m_size;
94
+ MMKVInfo("ashmem name:%s, size:%zu", m_diskFile.m_path.c_str(), m_size);
77
95
  auto ret = mmap();
78
96
  if (!ret) {
79
97
  doCleanMemoryCache(true);
@@ -90,13 +108,14 @@ MemoryFile::MemoryFile(int ashmemFD)
90
108
  namespace mmkv {
91
109
 
92
110
  constexpr auto ASHMEM_NAME_LEN = 256;
93
- constexpr auto __ASHMEMIOC = 0x77;
94
- # define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
95
- # define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
96
- # define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
97
- # define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
111
+ constexpr auto ASHMEM_IOC = 0x77;
112
+ # define ASHMEM_SET_NAME _IOW(ASHMEM_IOC, 1, char[ASHMEM_NAME_LEN])
113
+ # define ASHMEM_GET_NAME _IOR(ASHMEM_IOC, 2, char[ASHMEM_NAME_LEN])
114
+ # define ASHMEM_SET_SIZE _IOW(ASHMEM_IOC, 3, size_t)
115
+ # define ASHMEM_GET_SIZE _IO(ASHMEM_IOC, 4)
98
116
 
99
117
  int g_android_api = __ANDROID_API_L__;
118
+ std::string g_android_tmpDir = "/data/local/tmp/";
100
119
 
101
120
  void *loadLibrary() {
102
121
  auto name = "libandroid.so";
@@ -171,7 +190,7 @@ string ASharedMemory_getName(int fd) {
171
190
  // Android Q doesn't have ASharedMemory_getName()
172
191
  // I've make a request to Google, https://issuetracker.google.com/issues/130741665
173
192
  // There's nothing we can do before it's supported officially by Google
174
- if (g_android_api >= 29) {
193
+ if (g_android_api >= __ANDROID_API_Q__) {
175
194
  return "";
176
195
  }
177
196
 
@@ -180,7 +199,7 @@ string ASharedMemory_getName(int fd) {
180
199
  MMKVError("fail to get ashmem name:%d, %s", fd, strerror(errno));
181
200
  return "";
182
201
  }
183
- return string(name);
202
+ return {name};
184
203
  }
185
204
 
186
205
  } // namespace mmkv
@@ -0,0 +1,120 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making
3
+ * MMKV available.
4
+ *
5
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company.
6
+ * All rights reserved.
7
+ *
8
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use
9
+ * this file except in compliance with the License. You may obtain a copy of
10
+ * the License at
11
+ *
12
+ * https://opensource.org/licenses/BSD-3-Clause
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */
20
+
21
+ #include "MemoryFile.h"
22
+
23
+ #if defined(MMKV_ANDROID) || defined(MMKV_LINUX)
24
+ # include "InterProcessLock.h"
25
+ # include "MMBuffer.h"
26
+ # include "MMKVLog.h"
27
+ # include "ScopedLock.hpp"
28
+ # include <cerrno>
29
+ # include <utility>
30
+ # include <fcntl.h>
31
+ # include <sys/mman.h>
32
+ # include <sys/stat.h>
33
+ # include <unistd.h>
34
+ # include <sys/file.h>
35
+ # include <dirent.h>
36
+ # include <cstring>
37
+ # include <sys/sendfile.h>
38
+ # include <sys/syscall.h>
39
+
40
+ #ifdef MMKV_ANDROID
41
+ #include <dlfcn.h>
42
+ typedef int (*renameat2_t)(int old_dir_fd, const char* old_path, int new_dir_fd, const char* new_path, unsigned flags);
43
+ #endif
44
+
45
+ #ifndef RENAME_EXCHANGE
46
+ #define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
47
+ #endif
48
+
49
+ namespace mmkv {
50
+
51
+ extern bool getFileSize(int fd, size_t &size);
52
+
53
+ bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
54
+ bool renamed = false;
55
+
56
+ // try renameat2() first
57
+ #ifdef SYS_renameat2
58
+ #ifdef MMKV_ANDROID
59
+ static auto g_renameat2 = (renameat2_t) dlsym(RTLD_DEFAULT, "renameat2");
60
+ if (g_renameat2) {
61
+ renamed = (g_renameat2(AT_FDCWD, srcPath.c_str(), AT_FDCWD, dstPath.c_str(), RENAME_EXCHANGE) == 0);
62
+ }
63
+ #endif
64
+ if (!renamed) {
65
+ renamed = (syscall(SYS_renameat2, AT_FDCWD, srcPath.c_str(), AT_FDCWD, dstPath.c_str(), RENAME_EXCHANGE) == 0);
66
+ }
67
+ if (!renamed && errno != ENOENT) {
68
+ MMKVError("fail on renameat2() [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno, strerror(errno));
69
+ }
70
+ #endif // SYS_renameat2
71
+
72
+ if (!renamed) {
73
+ if (::rename(srcPath.c_str(), dstPath.c_str()) != 0) {
74
+ MMKVError("fail to rename [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno, strerror(errno));
75
+ return false;
76
+ }
77
+ }
78
+
79
+ ::unlink(srcPath.c_str());
80
+ return true;
81
+ }
82
+
83
+ // do it by sendfile()
84
+ bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) {
85
+ if (dstFD < 0) {
86
+ return false;
87
+ }
88
+ File srcFile(srcPath, OpenFlag::ReadOnly);
89
+ if (!srcFile.isFileValid()) {
90
+ return false;
91
+ }
92
+ auto srcFileSize = srcFile.getActualFileSize();
93
+
94
+ lseek(dstFD, 0, SEEK_SET);
95
+ auto writtenSize = ::sendfile(dstFD, srcFile.getFd(), nullptr, srcFileSize);
96
+ auto ret = (writtenSize == srcFileSize);
97
+ if (!ret) {
98
+ if (writtenSize < 0) {
99
+ MMKVError("fail to sendfile() %s to fd[%d], %d(%s)", srcPath.c_str(), dstFD, errno, strerror(errno));
100
+ } else {
101
+ MMKVError("sendfile() %s to fd[%d], written %lld < %zu", srcPath.c_str(), dstFD, writtenSize, srcFileSize);
102
+ }
103
+ } else if (needTruncate) {
104
+ size_t dstFileSize = 0;
105
+ getFileSize(dstFD, dstFileSize);
106
+ if ((dstFileSize != srcFileSize) && (::ftruncate(dstFD, static_cast<off_t>(srcFileSize)) != 0)) {
107
+ MMKVError("fail to truncate [%d] to size [%zu], %d(%s)", dstFD, srcFileSize, errno, strerror(errno));
108
+ ret = false;
109
+ }
110
+ }
111
+
112
+ if (ret) {
113
+ MMKVInfo("copy content from %s to fd[%d] finish", srcPath.c_str(), dstFD);
114
+ }
115
+ return ret;
116
+ }
117
+
118
+ } // namespace mmkv
119
+
120
+ #endif // defined(MMKV_ANDROID) || defined(MMKV_LINUX)
@@ -19,11 +19,10 @@
19
19
  */
20
20
 
21
21
  #include "MemoryFile.h"
22
+ #include "MMKVLog.h"
22
23
 
23
24
  #ifdef MMKV_IOS
24
25
 
25
- # include "MMKVLog.h"
26
-
27
26
  using namespace std;
28
27
 
29
28
  namespace mmkv {
@@ -50,3 +49,94 @@ void tryResetFileProtection(const string &path) {
50
49
  } // namespace mmkv
51
50
 
52
51
  #endif // MMKV_IOS
52
+
53
+ #ifdef MMKV_APPLE
54
+
55
+ #include <copyfile.h>
56
+ #include <mach/mach_time.h>
57
+
58
+ namespace mmkv {
59
+
60
+ bool tryAtomicRename(const char *src, const char *dst) {
61
+ bool renamed = false;
62
+
63
+ // try atomic swap first
64
+ if (@available(iOS 10.0, watchOS 3.0, *)) {
65
+ // renameat2() equivalent
66
+ if (renamex_np(src, dst, RENAME_SWAP) == 0) {
67
+ renamed = true;
68
+ } else if (errno != ENOENT) {
69
+ MMKVError("fail to renamex_np %s to %s, %s", src, dst, strerror(errno));
70
+ }
71
+ }
72
+
73
+ if (!renamed) {
74
+ // try old style rename
75
+ if (rename(src, dst) != 0) {
76
+ MMKVError("fail to rename %s to %s, %s", src, dst, strerror(errno));
77
+ return false;
78
+ }
79
+ }
80
+
81
+ unlink(src);
82
+
83
+ return true;
84
+ }
85
+
86
+ bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
87
+ // prepare a temp file for atomic rename, avoid data corruption of suddent crash
88
+ NSString *uniqueFileName = [NSString stringWithFormat:@"mmkv_%llu", mach_absolute_time()];
89
+ NSString *tmpFile = [NSTemporaryDirectory() stringByAppendingPathComponent:uniqueFileName];
90
+ if (copyfile(srcPath.c_str(), tmpFile.UTF8String, nullptr, COPYFILE_UNLINK | COPYFILE_CLONE) != 0) {
91
+ MMKVError("fail to copyfile [%s] to [%s], %s", srcPath.c_str(), tmpFile.UTF8String, strerror(errno));
92
+ return false;
93
+ }
94
+ MMKVInfo("copyfile [%s] to [%s]", srcPath.c_str(), tmpFile.UTF8String);
95
+
96
+ if (tryAtomicRename(tmpFile.UTF8String, dstPath.c_str())) {
97
+ MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());
98
+ return true;
99
+ }
100
+ unlink(tmpFile.UTF8String);
101
+ return false;
102
+ }
103
+
104
+ bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
105
+ File dstFile(dstPath, OpenFlag::WriteOnly | OpenFlag::Create | OpenFlag::Truncate);
106
+ if (!dstFile.isFileValid()) {
107
+ return false;
108
+ }
109
+ if (copyFileContent(srcPath, dstFile.getFd())) {
110
+ MMKVInfo("copy content from %s to fd[%s] finish", srcPath.c_str(), dstPath.c_str());
111
+ return true;
112
+ }
113
+ MMKVError("fail to copyfile(): target file %s", dstPath.c_str());
114
+ return false;
115
+ }
116
+
117
+ bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
118
+ if (dstFD < 0) {
119
+ return false;
120
+ }
121
+
122
+ File srcFile(srcPath, OpenFlag::ReadOnly);
123
+ if (!srcFile.isFileValid()) {
124
+ return false;
125
+ }
126
+
127
+ // sendfile() equivalent
128
+ if (::fcopyfile(srcFile.getFd(), dstFD, nullptr, COPYFILE_ACL | COPYFILE_STAT | COPYFILE_XATTR | COPYFILE_DATA) == 0) {
129
+ MMKVInfo("copy content from %s to fd[%d] finish", srcPath.c_str(), dstFD);
130
+ return true;
131
+ }
132
+ MMKVError("fail to copyfile(): %d(%s), source file %s", errno, strerror(errno), srcPath.c_str());
133
+ return false;
134
+ }
135
+
136
+ bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) {
137
+ return copyFileContent(srcPath, dstFD);
138
+ }
139
+
140
+ } // namespace mmkv
141
+
142
+ #endif // MMKV_APPLE