MemoryFile.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Tencent is pleased to support the open source community by making
  3. * MMKV available.
  4. *
  5. * Copyright (C) 2018 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. #ifndef MMKV_MAMERYFILE_H
  21. #define MMKV_MAMERYFILE_H
  22. #ifdef __cplusplus
  23. #include "MMKVPredef.h"
  24. #include <cstdint>
  25. #include <functional>
  26. #ifdef MMKV_ANDROID
  27. MMKVPath_t ashmemMMKVPathWithID(const MMKVPath_t &mmapID);
  28. long long getFileModifyTimeInMS(const char *path);
  29. namespace mmkv {
  30. extern int g_android_api;
  31. extern std::string g_android_tmpDir;
  32. enum FileType : bool { MMFILE_TYPE_FILE = false, MMFILE_TYPE_ASHMEM = true };
  33. } // namespace mmkv
  34. #endif // MMKV_ANDROID
  35. namespace mmkv {
  36. enum class OpenFlag : uint32_t {
  37. ReadOnly = 1 << 0,
  38. WriteOnly = 1 << 1,
  39. ReadWrite = ReadOnly | WriteOnly,
  40. Create = 1 << 2,
  41. Excel = 1 << 3, // fail if Create is set but the file already exist
  42. Truncate = 1 << 4,
  43. };
  44. constexpr uint32_t OpenFlagRWMask = 0x3; // mask for Read Write mode
  45. static inline OpenFlag operator | (OpenFlag left, OpenFlag right) {
  46. return static_cast<OpenFlag>(static_cast<uint32_t>(left) | static_cast<uint32_t>(right));
  47. }
  48. static inline bool operator & (OpenFlag left, OpenFlag right) {
  49. return ((static_cast<uint32_t>(left) & static_cast<uint32_t>(right)) != 0);
  50. }
  51. static inline OpenFlag operator & (OpenFlag left, uint32_t right) {
  52. return static_cast<OpenFlag>(static_cast<uint32_t>(left) & right);
  53. }
  54. template <typename T>
  55. T roundUp(T numToRound, T multiple) {
  56. return ((numToRound + multiple - 1) / multiple) * multiple;
  57. }
  58. class FileLock;
  59. class File {
  60. MMKVPath_t m_path;
  61. MMKVFileHandle_t m_fd;
  62. public:
  63. const OpenFlag m_flag;
  64. #ifndef MMKV_ANDROID
  65. explicit File(MMKVPath_t path, OpenFlag flag);
  66. #else
  67. File(MMKVPath_t path, OpenFlag flag, size_t size = 0, FileType fileType = MMFILE_TYPE_FILE);
  68. explicit File(MMKVFileHandle_t ashmemFD);
  69. size_t m_size;
  70. const FileType m_fileType;
  71. #endif // MMKV_ANDROID
  72. ~File() { close(); }
  73. bool open();
  74. void close();
  75. MMKVFileHandle_t getFd() { return m_fd; }
  76. const MMKVPath_t &getPath() const { return m_path; }
  77. #ifndef MMKV_WIN32
  78. bool isFileValid() const { return m_fd >= 0; }
  79. #else
  80. bool isFileValid() const { return m_fd != MMKVFileHandleInvalidValue; }
  81. #endif
  82. // get the actual file size on disk
  83. size_t getActualFileSize() const;
  84. // just forbid it for possibly misuse
  85. explicit File(const File &other) = delete;
  86. File &operator=(const File &other) = delete;
  87. friend class MemoryFile;
  88. };
  89. class MemoryFile {
  90. File m_diskFile;
  91. #ifdef MMKV_WIN32
  92. HANDLE m_fileMapping;
  93. #endif
  94. void *m_ptr;
  95. size_t m_size;
  96. const bool m_readOnly;
  97. const bool m_isMayflyFD;
  98. bool mmapOrCleanup(FileLock *fileLock);
  99. void doCleanMemoryCache(bool forceClean);
  100. bool openIfNeeded();
  101. public:
  102. #ifndef MMKV_ANDROID
  103. explicit MemoryFile(MMKVPath_t path, size_t expectedCapacity = 0, bool readOnly = false, bool mayflyFD = false);
  104. #else
  105. MemoryFile(MMKVPath_t path, size_t size, FileType fileType, size_t expectedCapacity = 0, bool readOnly = false, bool mayflyFD = false);
  106. explicit MemoryFile(MMKVFileHandle_t ashmemFD);
  107. const FileType m_fileType;
  108. #endif // MMKV_ANDROID
  109. ~MemoryFile() { doCleanMemoryCache(true); }
  110. size_t getFileSize() const { return m_size; }
  111. // get the actual file size on disk
  112. size_t getActualFileSize();
  113. void *getMemory() { return m_ptr; }
  114. const MMKVPath_t &getPath() { return m_diskFile.getPath(); }
  115. MMKVFileHandle_t getFd();
  116. void cleanMayflyFD();
  117. // the newly expanded file content will be zeroed
  118. bool truncate(size_t size, FileLock *fileLock = nullptr);
  119. bool msync(SyncFlag syncFlag);
  120. // call this if clearMemoryCache() has been called
  121. void reloadFromFile(size_t expectedCapacity = 0);
  122. void clearMemoryCache() { doCleanMemoryCache(false); }
  123. #ifndef MMKV_WIN32
  124. bool isFileValid() { return (m_isMayflyFD || m_diskFile.isFileValid()) && m_size > 0 && m_ptr; }
  125. #else
  126. bool isFileValid() { return (m_isMayflyFD || (m_diskFile.isFileValid() && m_fileMapping)) && m_size > 0 && m_ptr; }
  127. #endif
  128. // just forbid it for possibly misuse
  129. explicit MemoryFile(const MemoryFile &other) = delete;
  130. MemoryFile &operator=(const MemoryFile &other) = delete;
  131. };
  132. class MMBuffer;
  133. extern bool mkPath(const MMKVPath_t &path);
  134. extern bool isFileExist(const MMKVPath_t &nsFilePath);
  135. extern MMBuffer *readWholeFile(const MMKVPath_t &path);
  136. extern bool zeroFillFile(MMKVFileHandle_t fd, size_t startPos, size_t size);
  137. extern size_t getPageSize();
  138. extern MMKVPath_t absolutePath(const MMKVPath_t &path);
  139. #ifndef MMKV_WIN32
  140. extern bool getFileSize(int fd, size_t &size);
  141. #endif
  142. extern bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath);
  143. // copy file by potentially renaming target file, might change file inode
  144. extern bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath);
  145. // copy file by source file content, keep file inode the same
  146. extern bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath);
  147. extern bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD);
  148. extern bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate);
  149. //#if defined(MMKV_APPLE) || defined(MMKV_WIN32)
  150. bool isDiskOfMMAPFileCorrupted(MemoryFile *file, bool &needReportReadFail);
  151. //#endif
  152. bool deleteFile(const MMKVPath_t &path);
  153. enum WalkType : uint32_t {
  154. WalkFile = 1 << 0,
  155. WalkFolder = 1 << 1,
  156. };
  157. extern void walkInDir(const MMKVPath_t &dirPath, WalkType type, const std::function<void(const MMKVPath_t&, WalkType)> &walker);
  158. } // namespace mmkv
  159. #endif
  160. #endif //MMKV_MAMERYFILE_H