MMKV.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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_MMKV_H
  21. #define MMKV_MMKV_H
  22. #ifdef __cplusplus
  23. #include "MMBuffer.h"
  24. #include <cstdint>
  25. namespace mmkv {
  26. class CodedOutputData;
  27. class MemoryFile;
  28. class AESCrypt;
  29. struct MMKVMetaInfo;
  30. class FileLock;
  31. class InterProcessLock;
  32. class ThreadLock;
  33. } // namespace mmkv
  34. MMKV_NAMESPACE_BEGIN
  35. enum MMKVMode : uint32_t {
  36. MMKV_SINGLE_PROCESS = 1 << 0,
  37. MMKV_MULTI_PROCESS = 1 << 1,
  38. #ifdef MMKV_ANDROID
  39. CONTEXT_MODE_MULTI_PROCESS = 1 << 2, // in case someone mistakenly pass Context.MODE_MULTI_PROCESS
  40. MMKV_ASHMEM = 1 << 3,
  41. MMKV_BACKUP = 1 << 4,
  42. #endif
  43. };
  44. #define OUT
  45. class MMKV {
  46. #ifndef MMKV_ANDROID
  47. std::string m_mmapKey;
  48. MMKV(const std::string &mmapID, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath);
  49. #else // defined(MMKV_ANDROID)
  50. mmkv::FileLock *m_fileModeLock;
  51. mmkv::InterProcessLock *m_sharedProcessModeLock;
  52. mmkv::InterProcessLock *m_exclusiveProcessModeLock;
  53. MMKV(const std::string &mmapID, int size, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath);
  54. MMKV(const std::string &mmapID, int ashmemFD, int ashmemMetaFd, std::string *cryptKey = nullptr);
  55. #endif
  56. ~MMKV();
  57. std::string m_mmapID;
  58. MMKVPath_t m_path;
  59. MMKVPath_t m_crcPath;
  60. mmkv::MMKVMap *m_dic;
  61. mmkv::MMKVMapCrypt *m_dicCrypt;
  62. mmkv::MemoryFile *m_file;
  63. size_t m_actualSize;
  64. mmkv::CodedOutputData *m_output;
  65. bool m_needLoadFromFile;
  66. bool m_hasFullWriteback;
  67. uint32_t m_crcDigest;
  68. mmkv::MemoryFile *m_metaFile;
  69. mmkv::MMKVMetaInfo *m_metaInfo;
  70. mmkv::AESCrypt *m_crypter;
  71. mmkv::ThreadLock *m_lock;
  72. mmkv::FileLock *m_fileLock;
  73. mmkv::InterProcessLock *m_sharedProcessLock;
  74. mmkv::InterProcessLock *m_exclusiveProcessLock;
  75. #ifdef MMKV_APPLE
  76. using MMKVKey_t = NSString *__unsafe_unretained;
  77. static bool isKeyEmpty(MMKVKey_t key) { return key.length <= 0; }
  78. #else
  79. using MMKVKey_t = const std::string &;
  80. static bool isKeyEmpty(MMKVKey_t key) { return key.empty(); }
  81. #endif
  82. void loadFromFile();
  83. void partialLoadFromFile();
  84. void checkDataValid(bool &loadFromFile, bool &needFullWriteback);
  85. void checkLoadData();
  86. bool isFileValid();
  87. bool checkFileCRCValid(size_t actualSize, uint32_t crcDigest);
  88. void recaculateCRCDigestWithIV(const void *iv);
  89. void updateCRCDigest(const uint8_t *ptr, size_t length);
  90. size_t readActualSize();
  91. void oldStyleWriteActualSize(size_t actualSize);
  92. bool writeActualSize(size_t size, uint32_t crcDigest, const void *iv, bool increaseSequence);
  93. bool ensureMemorySize(size_t newSize);
  94. bool fullWriteback(mmkv::AESCrypt *newCrypter = nullptr);
  95. bool doFullWriteBack(std::pair<mmkv::MMBuffer, size_t> preparedData, mmkv::AESCrypt *newCrypter);
  96. mmkv::MMBuffer getDataForKey(MMKVKey_t key);
  97. // isDataHolder: avoid memory copying
  98. bool setDataForKey(mmkv::MMBuffer &&data, MMKVKey_t key, bool isDataHolder = false);
  99. bool removeDataForKey(MMKVKey_t key);
  100. using KVHolderRet_t = std::pair<bool, mmkv::KeyValueHolder>;
  101. // isDataHolder: avoid memory copying
  102. KVHolderRet_t doAppendDataWithKey(const mmkv::MMBuffer &data, const mmkv::MMBuffer &key, bool isDataHolder, uint32_t keyLength);
  103. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data, MMKVKey_t key, bool isDataHolder = false);
  104. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data, const mmkv::KeyValueHolder &kvHolder, bool isDataHolder = false);
  105. #ifdef MMKV_APPLE
  106. KVHolderRet_t appendDataWithKey(const mmkv::MMBuffer &data,
  107. MMKVKey_t key,
  108. const mmkv::KeyValueHolderCrypt &kvHolder,
  109. bool isDataHolder = false);
  110. #endif
  111. void notifyContentChanged();
  112. #if defined(MMKV_ANDROID) && !defined(MMKV_DISABLE_CRYPT)
  113. void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey);
  114. #endif
  115. static bool backupOneToDirectory(const std::string &mmapKey, const MMKVPath_t &dstPath, const MMKVPath_t &srcPath, bool compareFullPath);
  116. static size_t backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t &srcDir, bool isInSpecialDir);
  117. static bool restoreOneFromDirectory(const std::string &mmapKey, const MMKVPath_t &srcPath, const MMKVPath_t &dstPath, bool compareFullPath);
  118. static size_t restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t &dstDir, bool isInSpecialDir);
  119. public:
  120. // call this before getting any MMKV instance
  121. static void initializeMMKV(const MMKVPath_t &rootDir, MMKVLogLevel logLevel = MMKVLogInfo);
  122. #ifdef MMKV_APPLE
  123. // protect from some old code that don't call initializeMMKV()
  124. static void minimalInit(MMKVPath_t defaultRootDir);
  125. #endif
  126. // a generic purpose instance
  127. static MMKV *defaultMMKV(MMKVMode mode = MMKV_SINGLE_PROCESS, std::string *cryptKey = nullptr);
  128. #ifndef MMKV_ANDROID
  129. // mmapID: any unique ID (com.tencent.xin.pay, etc)
  130. // if you want a per-user mmkv, you could merge user-id within mmapID
  131. // cryptKey: 16 bytes at most
  132. static MMKV *mmkvWithID(const std::string &mmapID,
  133. MMKVMode mode = MMKV_SINGLE_PROCESS,
  134. std::string *cryptKey = nullptr,
  135. MMKVPath_t *rootPath = nullptr);
  136. #else // defined(MMKV_ANDROID)
  137. // mmapID: any unique ID (com.tencent.xin.pay, etc)
  138. // if you want a per-user mmkv, you could merge user-id within mmapID
  139. // cryptKey: 16 bytes at most
  140. static MMKV *mmkvWithID(const std::string &mmapID,
  141. int size = mmkv::DEFAULT_MMAP_SIZE,
  142. MMKVMode mode = MMKV_SINGLE_PROCESS,
  143. std::string *cryptKey = nullptr,
  144. MMKVPath_t *rootPath = nullptr);
  145. static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, int metaFD, std::string *cryptKey = nullptr);
  146. int ashmemFD();
  147. int ashmemMetaFD();
  148. bool checkProcessMode();
  149. #endif // MMKV_ANDROID
  150. // you can call this on application termination, it's totally fine if you don't call
  151. static void onExit();
  152. const std::string &mmapID() const;
  153. const bool m_isInterProcess;
  154. #ifndef MMKV_DISABLE_CRYPT
  155. std::string cryptKey() const;
  156. // transform plain text into encrypted text, or vice versa with empty cryptKey
  157. // you can change existing crypt key with different cryptKey
  158. bool reKey(const std::string &cryptKey);
  159. // just reset cryptKey (will not encrypt or decrypt anything)
  160. // usually you should call this method after other process reKey() the multi-process mmkv
  161. void checkReSetCryptKey(const std::string *cryptKey);
  162. #endif
  163. bool set(bool value, MMKVKey_t key);
  164. bool set(int32_t value, MMKVKey_t key);
  165. bool set(uint32_t value, MMKVKey_t key);
  166. bool set(int64_t value, MMKVKey_t key);
  167. bool set(uint64_t value, MMKVKey_t key);
  168. bool set(float value, MMKVKey_t key);
  169. bool set(double value, MMKVKey_t key);
  170. // avoid unexpected type conversion (pointer to bool, etc)
  171. template <typename T>
  172. bool set(T value, MMKVKey_t key) = delete;
  173. #ifdef MMKV_APPLE
  174. bool set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key);
  175. NSObject *getObject(MMKVKey_t key, Class cls);
  176. #else // !defined(MMKV_APPLE)
  177. bool set(const char *value, MMKVKey_t key);
  178. bool set(const std::string &value, MMKVKey_t key);
  179. bool set(const mmkv::MMBuffer &value, MMKVKey_t key);
  180. bool set(const std::vector<std::string> &vector, MMKVKey_t key);
  181. bool getString(MMKVKey_t key, std::string &result);
  182. mmkv::MMBuffer getBytes(MMKVKey_t key);
  183. bool getBytes(MMKVKey_t key, mmkv::MMBuffer &result);
  184. bool getVector(MMKVKey_t key, std::vector<std::string> &result);
  185. #endif // MMKV_APPLE
  186. bool getBool(MMKVKey_t key, bool defaultValue = false, OUT bool *hasValue = nullptr);
  187. int32_t getInt32(MMKVKey_t key, int32_t defaultValue = 0, OUT bool *hasValue = nullptr);
  188. uint32_t getUInt32(MMKVKey_t key, uint32_t defaultValue = 0, OUT bool *hasValue = nullptr);
  189. int64_t getInt64(MMKVKey_t key, int64_t defaultValue = 0, OUT bool *hasValue = nullptr);
  190. uint64_t getUInt64(MMKVKey_t key, uint64_t defaultValue = 0, OUT bool *hasValue = nullptr);
  191. float getFloat(MMKVKey_t key, float defaultValue = 0, OUT bool *hasValue = nullptr);
  192. double getDouble(MMKVKey_t key, double defaultValue = 0, OUT bool *hasValue = nullptr);
  193. // return the actual size consumption of the key's value
  194. // pass actualSize = true to get value's length
  195. size_t getValueSize(MMKVKey_t key, bool actualSize);
  196. // return size written into buffer
  197. // return -1 on any error
  198. int32_t writeValueToBuffer(MMKVKey_t key, void *ptr, int32_t size);
  199. bool containsKey(MMKVKey_t key);
  200. size_t count();
  201. size_t totalSize();
  202. size_t actualSize();
  203. #ifdef MMKV_APPLE
  204. NSArray *allKeys();
  205. void removeValuesForKeys(NSArray *arrKeys);
  206. typedef void (^EnumerateBlock)(NSString *key, BOOL *stop);
  207. void enumerateKeys(EnumerateBlock block);
  208. # ifdef MMKV_IOS
  209. static void setIsInBackground(bool isInBackground);
  210. static bool isInBackground();
  211. # endif
  212. #else // !defined(MMKV_APPLE)
  213. std::vector<std::string> allKeys();
  214. void removeValuesForKeys(const std::vector<std::string> &arrKeys);
  215. #endif // MMKV_APPLE
  216. void removeValueForKey(MMKVKey_t key);
  217. void clearAll();
  218. // MMKV's size won't reduce after deleting key-values
  219. // call this method after lots of deleting if you care about disk usage
  220. // note that `clearAll` has the similar effect of `trim`
  221. void trim();
  222. // call this method if the instance is no longer needed in the near future
  223. // any subsequent call to the instance is undefined behavior
  224. void close();
  225. // call this method if you are facing memory-warning
  226. // any subsequent call to the instance will load all key-values from file again
  227. void clearMemoryCache();
  228. // you don't need to call this, really, I mean it
  229. // unless you worry about running out of battery
  230. void sync(SyncFlag flag = MMKV_SYNC);
  231. // get exclusive access
  232. void lock();
  233. void unlock();
  234. bool try_lock();
  235. static const MMKVPath_t &getRootDir();
  236. // backup one MMKV instance from srcDir to dstDir
  237. // if srcDir is null, then backup from the root dir of MMKV
  238. static bool backupOneToDirectory(const std::string &mmapID, const MMKVPath_t &dstDir, const MMKVPath_t *srcDir = nullptr);
  239. // restore one MMKV instance from srcDir to dstDir
  240. // if dstDir is null, then restore to the root dir of MMKV
  241. static bool restoreOneFromDirectory(const std::string &mmapID, const MMKVPath_t &srcDir, const MMKVPath_t *dstDir = nullptr);
  242. // backup all MMKV instance from srcDir to dstDir
  243. // if srcDir is null, then backup from the root dir of MMKV
  244. // return count of MMKV successfully backuped
  245. static size_t backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t *srcDir = nullptr);
  246. // restore all MMKV instance from srcDir to dstDir
  247. // if dstDir is null, then restore to the root dir of MMKV
  248. // return count of MMKV successfully restored
  249. static size_t restoreAllFromDirectory(const MMKVPath_t &srcDir, const MMKVPath_t *dstDir = nullptr);
  250. // check if content been changed by other process
  251. void checkContentChanged();
  252. // called when content is changed by other process
  253. // doesn't guarantee real-time notification
  254. static void registerContentChangeHandler(mmkv::ContentChangeHandler handler);
  255. static void unRegisterContentChangeHandler();
  256. // by default MMKV will discard all datas on failure
  257. // return `OnErrorRecover` to recover any data from file
  258. static void registerErrorHandler(mmkv::ErrorHandler handler);
  259. static void unRegisterErrorHandler();
  260. // MMKVLogInfo by default
  261. // pass MMKVLogNone to disable all logging
  262. static void setLogLevel(MMKVLogLevel level);
  263. // by default MMKV will print log to the console
  264. // implement this method to redirect MMKV's log
  265. static void registerLogHandler(mmkv::LogHandler handler);
  266. static void unRegisterLogHandler();
  267. // detect if the MMKV file is valid or not
  268. // Note: Don't use this to check the existence of the instance, the return value is undefined if the file was never created.
  269. static bool isFileValid(const std::string &mmapID, MMKVPath_t *relatePath = nullptr);
  270. // just forbid it for possibly misuse
  271. explicit MMKV(const MMKV &other) = delete;
  272. MMKV &operator=(const MMKV &other) = delete;
  273. };
  274. MMKV_NAMESPACE_END
  275. #endif
  276. #endif // MMKV_MMKV_H