react-native-mmkv 2.11.0 → 2.12.0
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.
- package/MMKV/Core/CodedInputData.cpp +28 -4
- package/MMKV/Core/CodedInputData.h +5 -1
- package/MMKV/Core/CodedOutputData.cpp +12 -0
- package/MMKV/Core/CodedOutputData.h +6 -0
- package/MMKV/Core/MMBuffer.cpp +7 -0
- package/MMKV/Core/MMBuffer.h +3 -0
- package/MMKV/Core/MMKV.cpp +114 -19
- package/MMKV/Core/MMKV.h +69 -33
- package/MMKV/Core/MMKVPredef.h +1 -1
- package/MMKV/Core/MMKV_Android.cpp +10 -8
- package/MMKV/Core/MMKV_IO.cpp +386 -60
- package/MMKV/Core/MMKV_OSX.cpp +51 -30
- package/MMKV/Core/MMKV_OSX.h +10 -4
- package/MMKV/Core/MemoryFile.cpp +31 -11
- package/MMKV/Core/MemoryFile.h +8 -3
- package/MMKV/Core/MemoryFile_Android.cpp +2 -2
- package/MMKV/Core/MemoryFile_OSX.cpp +2 -3
- package/MMKV/Core/MemoryFile_Win32.cpp +8 -5
- package/MMKV/Core/MiniPBCoder.cpp +11 -0
- package/MMKV/Core/MiniPBCoder.h +3 -0
- package/MMKV/Core/MiniPBCoder_OSX.cpp +8 -0
- package/MMKV/Core/ThreadLock.cpp +5 -0
- package/MMKV/Core/ThreadLock.h +4 -0
- package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +8 -0
- package/MMKV/Core/core.vcxproj +3 -3
- package/MMKV/README.md +3 -3
- package/android/build.gradle +16 -3
- package/android/src/hasNamespace/AndroidManifest.xml +3 -0
- package/android/src/main/cpp/cpp-adapter.cpp +7 -1
- package/ios/MmkvModule.mm +8 -2
- package/lib/commonjs/createMMKV.web.js +1 -1
- package/lib/commonjs/createMMKV.web.js.map +1 -1
- package/lib/commonjs/hooks.js +15 -10
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/module/createMMKV.web.js +1 -1
- package/lib/module/createMMKV.web.js.map +1 -1
- package/lib/module/hooks.js +15 -10
- package/lib/module/hooks.js.map +1 -1
- package/lib/typescript/createMMKV.web.d.ts.map +1 -1
- package/lib/typescript/hooks.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native-mmkv.podspec +1 -1
- package/src/createMMKV.web.ts +4 -2
- package/src/hooks.ts +18 -13
- package/MMKV/LICENSE.TXT +0 -193
package/MMKV/Core/MMKV_IO.cpp
CHANGED
|
@@ -52,6 +52,8 @@
|
|
|
52
52
|
using namespace std;
|
|
53
53
|
using namespace mmkv;
|
|
54
54
|
using KVHolderRet_t = std::pair<bool, KeyValueHolder>;
|
|
55
|
+
extern ThreadLock *g_instanceLock;
|
|
56
|
+
extern unordered_map<string, MMKV *> *g_instanceDic;
|
|
55
57
|
|
|
56
58
|
MMKV_NAMESPACE_BEGIN
|
|
57
59
|
|
|
@@ -65,7 +67,7 @@ void MMKV::loadFromFile() {
|
|
|
65
67
|
}
|
|
66
68
|
#endif
|
|
67
69
|
if (!m_file->isFileValid()) {
|
|
68
|
-
m_file->reloadFromFile();
|
|
70
|
+
m_file->reloadFromFile(m_expectedCapacity);
|
|
69
71
|
}
|
|
70
72
|
if (!m_file->isFileValid()) {
|
|
71
73
|
MMKVError("file [%s] not valid", m_path.c_str());
|
|
@@ -132,6 +134,9 @@ void MMKV::loadFromFile() {
|
|
|
132
134
|
|
|
133
135
|
// read from last m_position
|
|
134
136
|
void MMKV::partialLoadFromFile() {
|
|
137
|
+
if (!m_file->isFileValid()) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
135
140
|
m_metaInfo->read(m_metaFile->getMemory());
|
|
136
141
|
|
|
137
142
|
size_t oldActualSize = m_actualSize;
|
|
@@ -187,7 +192,8 @@ void MMKV::loadMetaInfoAndCheck() {
|
|
|
187
192
|
m_metaInfo->read(m_metaFile->getMemory());
|
|
188
193
|
// the meta file is in specious status
|
|
189
194
|
if (m_metaInfo->m_version >= MMKVVersionHolder) {
|
|
190
|
-
MMKVWarning("meta file [%s] in specious state, version %u, flags 0x%llx", m_mmapID.c_str(),
|
|
195
|
+
MMKVWarning("meta file [%s] in specious state, version %u, flags 0x%llx", m_mmapID.c_str(),
|
|
196
|
+
m_metaInfo->m_version, m_metaInfo->m_flags);
|
|
191
197
|
|
|
192
198
|
// MMKVVersionActualSize is the last version we don't check meta file
|
|
193
199
|
m_metaInfo->m_version = MMKVVersionActualSize;
|
|
@@ -197,6 +203,10 @@ void MMKV::loadMetaInfoAndCheck() {
|
|
|
197
203
|
|
|
198
204
|
if (m_metaInfo->m_version >= MMKVVersionFlag) {
|
|
199
205
|
m_enableKeyExpire = m_metaInfo->hasFlag(MMKVMetaInfo::EnableKeyExipre);
|
|
206
|
+
if (m_enableKeyExpire && m_enableCompareBeforeSet) {
|
|
207
|
+
MMKVError("enableCompareBeforeSet will be invalid when Expiration is on");
|
|
208
|
+
m_enableCompareBeforeSet = false;
|
|
209
|
+
}
|
|
200
210
|
MMKVInfo("meta file [%s] has flag [%llu]", m_mmapID.c_str(), m_metaInfo->m_flags);
|
|
201
211
|
} else {
|
|
202
212
|
if (m_metaInfo->m_flags != 0) {
|
|
@@ -253,8 +263,8 @@ void MMKV::checkDataValid(bool &loadFromFile, bool &needFullWriteback) {
|
|
|
253
263
|
loadFromFile = true;
|
|
254
264
|
} else {
|
|
255
265
|
checkLastConfirmedInfo();
|
|
256
|
-
|
|
257
266
|
if (!loadFromFile) {
|
|
267
|
+
|
|
258
268
|
auto strategic = onMMKVCRCCheckFail(m_mmapID);
|
|
259
269
|
if (strategic == OnErrorRecover) {
|
|
260
270
|
loadFromFile = true;
|
|
@@ -392,22 +402,25 @@ bool MMKV::ensureMemorySize(size_t newSize) {
|
|
|
392
402
|
}
|
|
393
403
|
// try a full rewrite to make space
|
|
394
404
|
auto preparedData = m_crypter ? prepareEncode(*m_dicCrypt) : prepareEncode(*m_dic);
|
|
395
|
-
|
|
405
|
+
// dic.empty() means inserting key-value for the first time, no need to call msync()
|
|
406
|
+
return expandAndWriteBack(newSize, std::move(preparedData), m_crypter ? !m_dicCrypt->empty() : !m_dic->empty());
|
|
396
407
|
}
|
|
397
408
|
return true;
|
|
398
409
|
}
|
|
399
410
|
|
|
400
411
|
// try a full rewrite to make space
|
|
401
|
-
bool MMKV::expandAndWriteBack(size_t newSize, std::pair<mmkv::MMBuffer, size_t> preparedData) {
|
|
412
|
+
bool MMKV::expandAndWriteBack(size_t newSize, std::pair<mmkv::MMBuffer, size_t> preparedData, bool needSync) {
|
|
402
413
|
auto fileSize = m_file->getFileSize();
|
|
403
414
|
auto sizeOfDic = preparedData.second;
|
|
404
415
|
size_t lenNeeded = sizeOfDic + Fixed32Size + newSize;
|
|
405
|
-
size_t
|
|
406
|
-
size_t
|
|
407
|
-
|
|
416
|
+
size_t nowDicCount = m_crypter ? m_dicCrypt->size() : m_dic->size();
|
|
417
|
+
size_t laterDicCount = std::max<size_t>(1, nowDicCount + 1);
|
|
418
|
+
// or use <cmath> ceil()
|
|
419
|
+
size_t avgItemSize = (lenNeeded + laterDicCount - 1) / laterDicCount;
|
|
420
|
+
size_t futureUsage = avgItemSize * std::max<size_t>(8, laterDicCount / 2);
|
|
408
421
|
// 1. no space for a full rewrite, double it
|
|
409
422
|
// 2. or space is not large enough for future usage, double it to avoid frequently full rewrite
|
|
410
|
-
if (lenNeeded >= fileSize || (lenNeeded + futureUsage) >= fileSize) {
|
|
423
|
+
if (lenNeeded >= fileSize || (needSync && (lenNeeded + futureUsage) >= fileSize)) {
|
|
411
424
|
size_t oldSize = fileSize;
|
|
412
425
|
do {
|
|
413
426
|
fileSize *= 2;
|
|
@@ -416,6 +429,7 @@ bool MMKV::expandAndWriteBack(size_t newSize, std::pair<mmkv::MMBuffer, size_t>
|
|
|
416
429
|
oldSize, fileSize, newSize, futureUsage);
|
|
417
430
|
|
|
418
431
|
// if we can't extend size, rollback to old state
|
|
432
|
+
// this is a good place to mock enlarging file failure
|
|
419
433
|
if (!m_file->truncate(fileSize)) {
|
|
420
434
|
return false;
|
|
421
435
|
}
|
|
@@ -426,7 +440,7 @@ bool MMKV::expandAndWriteBack(size_t newSize, std::pair<mmkv::MMBuffer, size_t>
|
|
|
426
440
|
return false;
|
|
427
441
|
}
|
|
428
442
|
}
|
|
429
|
-
return doFullWriteBack(std::move(preparedData), nullptr);
|
|
443
|
+
return doFullWriteBack(std::move(preparedData), nullptr, needSync);
|
|
430
444
|
}
|
|
431
445
|
|
|
432
446
|
size_t MMKV::readActualSize() {
|
|
@@ -573,10 +587,21 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) {
|
|
|
573
587
|
}
|
|
574
588
|
auto itr = m_dicCrypt->find(key);
|
|
575
589
|
if (itr != m_dicCrypt->end()) {
|
|
590
|
+
bool onlyOneKey = !m_isInterProcess && m_dicCrypt->size() == 1;
|
|
576
591
|
# ifdef MMKV_APPLE
|
|
577
|
-
|
|
592
|
+
KVHolderRet_t ret;
|
|
593
|
+
if (onlyOneKey) {
|
|
594
|
+
ret = overrideDataWithKey(data, key, itr->second, isDataHolder);
|
|
595
|
+
} else {
|
|
596
|
+
ret = appendDataWithKey(data, key, itr->second, isDataHolder);
|
|
597
|
+
}
|
|
578
598
|
# else
|
|
579
|
-
|
|
599
|
+
KVHolderRet_t ret;
|
|
600
|
+
if (onlyOneKey) {
|
|
601
|
+
ret = overrideDataWithKey(data, key, isDataHolder);
|
|
602
|
+
} else {
|
|
603
|
+
ret = appendDataWithKey(data, key, isDataHolder);
|
|
604
|
+
}
|
|
580
605
|
# endif
|
|
581
606
|
if (!ret.first) {
|
|
582
607
|
return false;
|
|
@@ -597,11 +622,17 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) {
|
|
|
597
622
|
} else {
|
|
598
623
|
// in case filterExpiredKeys() is triggered
|
|
599
624
|
m_dicCrypt->emplace(key, std::move(kvHolder));
|
|
600
|
-
|
|
625
|
+
mmkv_retain_key(key);
|
|
601
626
|
}
|
|
602
627
|
}
|
|
603
628
|
} else {
|
|
604
|
-
|
|
629
|
+
bool needOverride = !m_isInterProcess && m_dicCrypt->empty() && m_actualSize > 0;
|
|
630
|
+
KVHolderRet_t ret;
|
|
631
|
+
if (needOverride) {
|
|
632
|
+
ret = overrideDataWithKey(data, key, isDataHolder);
|
|
633
|
+
} else {
|
|
634
|
+
ret = appendDataWithKey(data, key, isDataHolder);
|
|
635
|
+
}
|
|
605
636
|
if (!ret.first) {
|
|
606
637
|
return false;
|
|
607
638
|
}
|
|
@@ -614,21 +645,58 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) {
|
|
|
614
645
|
} else {
|
|
615
646
|
m_dicCrypt->emplace(key, KeyValueHolderCrypt(std::move(data)));
|
|
616
647
|
}
|
|
617
|
-
|
|
648
|
+
mmkv_retain_key(key);
|
|
618
649
|
}
|
|
619
650
|
} else
|
|
620
651
|
#endif // MMKV_DISABLE_CRYPT
|
|
621
652
|
{
|
|
622
653
|
auto itr = m_dic->find(key);
|
|
623
654
|
if (itr != m_dic->end()) {
|
|
655
|
+
// compare data before appending to file
|
|
656
|
+
if (isCompareBeforeSetEnabled()) {
|
|
657
|
+
auto basePtr = (uint8_t *) (m_file->getMemory()) + Fixed32Size;
|
|
658
|
+
MMBuffer oldValueData = itr->second.toMMBuffer(basePtr);
|
|
659
|
+
if (isDataHolder) {
|
|
660
|
+
CodedInputData inputData(oldValueData.getPtr(), oldValueData.length());
|
|
661
|
+
try {
|
|
662
|
+
// read extra holder header bytes and to real MMBuffer
|
|
663
|
+
oldValueData = CodedInputData::readRealData(oldValueData);
|
|
664
|
+
if (oldValueData == data) {
|
|
665
|
+
// MMKVInfo("[key] %s, set the same data", key.c_str());
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
} catch (std::exception &exception) {
|
|
669
|
+
MMKVError("compareBeforeSet exception: %s", exception.what());
|
|
670
|
+
} catch (...) {
|
|
671
|
+
MMKVError("compareBeforeSet fail");
|
|
672
|
+
}
|
|
673
|
+
} else {
|
|
674
|
+
if (oldValueData == data) {
|
|
675
|
+
// MMKVInfo("[key] %s, set the same data", key.c_str());
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
bool onlyOneKey = !m_isInterProcess && m_dic->size() == 1;
|
|
624
682
|
if (likely(!m_enableKeyExpire)) {
|
|
625
|
-
|
|
683
|
+
KVHolderRet_t ret;
|
|
684
|
+
if (onlyOneKey) {
|
|
685
|
+
ret = overrideDataWithKey(data, itr->second, isDataHolder);
|
|
686
|
+
} else {
|
|
687
|
+
ret = appendDataWithKey(data, itr->second, isDataHolder);
|
|
688
|
+
}
|
|
626
689
|
if (!ret.first) {
|
|
627
690
|
return false;
|
|
628
691
|
}
|
|
629
692
|
itr->second = std::move(ret.second);
|
|
630
693
|
} else {
|
|
631
|
-
|
|
694
|
+
KVHolderRet_t ret;
|
|
695
|
+
if (onlyOneKey) {
|
|
696
|
+
ret = overrideDataWithKey(data, key, isDataHolder);
|
|
697
|
+
} else {
|
|
698
|
+
ret = appendDataWithKey(data, key, isDataHolder);
|
|
699
|
+
}
|
|
632
700
|
if (!ret.first) {
|
|
633
701
|
return false;
|
|
634
702
|
}
|
|
@@ -638,16 +706,22 @@ bool MMKV::setDataForKey(MMBuffer &&data, MMKVKey_t key, bool isDataHolder) {
|
|
|
638
706
|
} else {
|
|
639
707
|
// in case filterExpiredKeys() is triggered
|
|
640
708
|
m_dic->emplace(key, std::move(ret.second));
|
|
641
|
-
|
|
709
|
+
mmkv_retain_key(key);
|
|
642
710
|
}
|
|
643
711
|
}
|
|
644
712
|
} else {
|
|
645
|
-
|
|
713
|
+
bool needOverride = !m_isInterProcess && m_dic->empty() && m_actualSize > 0;
|
|
714
|
+
KVHolderRet_t ret;
|
|
715
|
+
if (needOverride) {
|
|
716
|
+
ret = overrideDataWithKey(data, key, isDataHolder);
|
|
717
|
+
} else {
|
|
718
|
+
ret = appendDataWithKey(data, key, isDataHolder);
|
|
719
|
+
}
|
|
646
720
|
if (!ret.first) {
|
|
647
721
|
return false;
|
|
648
722
|
}
|
|
649
723
|
m_dic->emplace(key, std::move(ret.second));
|
|
650
|
-
|
|
724
|
+
mmkv_retain_key(key);
|
|
651
725
|
}
|
|
652
726
|
}
|
|
653
727
|
m_hasFullWriteback = false;
|
|
@@ -772,6 +846,9 @@ MMKV::doAppendDataWithKey(const MMBuffer &data, const MMBuffer &keyData, bool is
|
|
|
772
846
|
} catch (std::exception &e) {
|
|
773
847
|
MMKVError("%s", e.what());
|
|
774
848
|
return make_pair(false, KeyValueHolder());
|
|
849
|
+
} catch (...) {
|
|
850
|
+
MMKVError("append fail");
|
|
851
|
+
return make_pair(false, KeyValueHolder());
|
|
775
852
|
}
|
|
776
853
|
|
|
777
854
|
auto offset = static_cast<uint32_t>(m_actualSize);
|
|
@@ -787,6 +864,97 @@ MMKV::doAppendDataWithKey(const MMBuffer &data, const MMBuffer &keyData, bool is
|
|
|
787
864
|
return make_pair(true, KeyValueHolder(originKeyLength, valueLength, offset));
|
|
788
865
|
}
|
|
789
866
|
|
|
867
|
+
KVHolderRet_t MMKV::doOverrideDataWithKey(const MMBuffer &data,
|
|
868
|
+
const MMBuffer &keyData,
|
|
869
|
+
bool isDataHolder,
|
|
870
|
+
uint32_t originKeyLength) {
|
|
871
|
+
auto isKeyEncoded = (originKeyLength < keyData.length());
|
|
872
|
+
auto keyLength = static_cast<uint32_t>(keyData.length());
|
|
873
|
+
auto valueLength = static_cast<uint32_t>(data.length());
|
|
874
|
+
if (isDataHolder) {
|
|
875
|
+
valueLength += pbRawVarint32Size(valueLength);
|
|
876
|
+
}
|
|
877
|
+
// size needed to encode the key
|
|
878
|
+
size_t size = isKeyEncoded ? keyLength : (keyLength + pbRawVarint32Size(keyLength));
|
|
879
|
+
// size needed to encode the value
|
|
880
|
+
size += valueLength + pbRawVarint32Size(valueLength);
|
|
881
|
+
|
|
882
|
+
if (!checkSizeForOverride(size)) {
|
|
883
|
+
return doAppendDataWithKey(data, keyData, isDataHolder, originKeyLength);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// we don't not support override in multi-process mode
|
|
887
|
+
// SCOPED_LOCK(m_exclusiveProcessLock);
|
|
888
|
+
|
|
889
|
+
#ifdef MMKV_IOS
|
|
890
|
+
auto ret = guardForBackgroundWriting(m_output->curWritePointer(), size);
|
|
891
|
+
if (!ret.first) {
|
|
892
|
+
return make_pair(false, KeyValueHolder());
|
|
893
|
+
}
|
|
894
|
+
#endif
|
|
895
|
+
#ifndef MMKV_DISABLE_CRYPT
|
|
896
|
+
if (m_crypter) {
|
|
897
|
+
if (m_metaInfo->m_version >= MMKVVersionRandomIV) {
|
|
898
|
+
m_crypter->resetIV(m_metaInfo->m_vector, sizeof(m_metaInfo->m_vector));
|
|
899
|
+
} else {
|
|
900
|
+
m_crypter->resetIV();
|
|
901
|
+
}
|
|
902
|
+
if (KeyValueHolderCrypt::isValueStoredAsOffset(valueLength)) {
|
|
903
|
+
m_crypter->getCurStatus(t_status);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
#endif
|
|
907
|
+
try {
|
|
908
|
+
// write ItemSizeHolder
|
|
909
|
+
m_output->setPosition(0);
|
|
910
|
+
m_output->writeRawVarint32(ItemSizeHolder);
|
|
911
|
+
m_actualSize = ItemSizeHolderSize;
|
|
912
|
+
|
|
913
|
+
if (isKeyEncoded) {
|
|
914
|
+
m_output->writeRawData(keyData);
|
|
915
|
+
} else {
|
|
916
|
+
m_output->writeData(keyData);
|
|
917
|
+
}
|
|
918
|
+
if (isDataHolder) {
|
|
919
|
+
m_output->writeRawVarint32((int32_t) valueLength);
|
|
920
|
+
}
|
|
921
|
+
m_output->writeData(data); // note: write size of data
|
|
922
|
+
} catch (std::exception &e) {
|
|
923
|
+
MMKVError("%s", e.what());
|
|
924
|
+
return make_pair(false, KeyValueHolder());
|
|
925
|
+
} catch (...) {
|
|
926
|
+
MMKVError("append fail");
|
|
927
|
+
return make_pair(false, KeyValueHolder());
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
auto offset = static_cast<uint32_t>(m_actualSize);
|
|
931
|
+
m_actualSize += size;
|
|
932
|
+
auto ptr = (uint8_t *) m_file->getMemory() + Fixed32Size;
|
|
933
|
+
#ifndef MMKV_DISABLE_CRYPT
|
|
934
|
+
if (m_crypter) {
|
|
935
|
+
m_crypter->encrypt(ptr, ptr, m_actualSize);
|
|
936
|
+
}
|
|
937
|
+
#endif
|
|
938
|
+
recaculateCRCDigestOnly();
|
|
939
|
+
|
|
940
|
+
return make_pair(true, KeyValueHolder(originKeyLength, valueLength, offset));
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
bool MMKV::checkSizeForOverride(size_t size) {
|
|
944
|
+
if (!isFileValid()) {
|
|
945
|
+
MMKVWarning("[%s] file not valid", m_mmapID.c_str());
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// only override if the file can hole it without ftruncate()
|
|
950
|
+
auto fileSize = m_file->getFileSize();
|
|
951
|
+
auto spaceNeededForOverride = size + Fixed32Size + ItemSizeHolderSize;
|
|
952
|
+
if (size > fileSize || spaceNeededForOverride > fileSize) {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
|
|
790
958
|
KVHolderRet_t MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t key, bool isDataHolder) {
|
|
791
959
|
#ifdef MMKV_APPLE
|
|
792
960
|
auto oData = [key dataUsingEncoding:NSUTF8StringEncoding];
|
|
@@ -797,6 +965,16 @@ KVHolderRet_t MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t key, bool
|
|
|
797
965
|
return doAppendDataWithKey(data, keyData, isDataHolder, static_cast<uint32_t>(keyData.length()));
|
|
798
966
|
}
|
|
799
967
|
|
|
968
|
+
KVHolderRet_t MMKV::overrideDataWithKey(const MMBuffer &data, MMKVKey_t key, bool isDataHolder) {
|
|
969
|
+
#ifdef MMKV_APPLE
|
|
970
|
+
auto oData = [key dataUsingEncoding:NSUTF8StringEncoding];
|
|
971
|
+
auto keyData = MMBuffer(oData, MMBufferNoCopy);
|
|
972
|
+
#else
|
|
973
|
+
auto keyData = MMBuffer((void *) key.data(), key.size(), MMBufferNoCopy);
|
|
974
|
+
#endif
|
|
975
|
+
return doOverrideDataWithKey(data, keyData, isDataHolder, static_cast<uint32_t>(keyData.length()));
|
|
976
|
+
}
|
|
977
|
+
|
|
800
978
|
KVHolderRet_t MMKV::appendDataWithKey(const MMBuffer &data, const KeyValueHolder &kvHolder, bool isDataHolder) {
|
|
801
979
|
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
802
980
|
|
|
@@ -822,7 +1000,35 @@ KVHolderRet_t MMKV::appendDataWithKey(const MMBuffer &data, const KeyValueHolder
|
|
|
822
1000
|
return doAppendDataWithKey(data, keyData, isDataHolder, keyLength);
|
|
823
1001
|
}
|
|
824
1002
|
|
|
825
|
-
|
|
1003
|
+
// only one key in dict, do not append, just rewrite from beginning
|
|
1004
|
+
KVHolderRet_t MMKV::overrideDataWithKey(const MMBuffer &data, const KeyValueHolder &kvHolder, bool isDataHolder) {
|
|
1005
|
+
// we don't not support override in multi-process mode
|
|
1006
|
+
// SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1007
|
+
|
|
1008
|
+
uint32_t keyLength = kvHolder.keySize;
|
|
1009
|
+
// size needed to encode the key
|
|
1010
|
+
size_t rawKeySize = keyLength + pbRawVarint32Size(keyLength);
|
|
1011
|
+
|
|
1012
|
+
// ensureMemorySize() (inside doAppendDataWithKey() which be called from doOverrideDataWithKey())
|
|
1013
|
+
// might change kvHolder.offset, so have to do it early
|
|
1014
|
+
{
|
|
1015
|
+
auto valueLength = static_cast<uint32_t>(data.length());
|
|
1016
|
+
if (isDataHolder) {
|
|
1017
|
+
valueLength += pbRawVarint32Size(valueLength);
|
|
1018
|
+
}
|
|
1019
|
+
auto size = rawKeySize + valueLength + pbRawVarint32Size(valueLength);
|
|
1020
|
+
bool hasEnoughSize = checkSizeForOverride(size);
|
|
1021
|
+
if (!hasEnoughSize) {
|
|
1022
|
+
return appendDataWithKey(data, kvHolder, isDataHolder);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
auto basePtr = (uint8_t *) m_file->getMemory() + Fixed32Size;
|
|
1026
|
+
MMBuffer keyData(basePtr + kvHolder.offset, rawKeySize, MMBufferNoCopy);
|
|
1027
|
+
|
|
1028
|
+
return doOverrideDataWithKey(data, keyData, isDataHolder, keyLength);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
bool MMKV::fullWriteback(AESCrypt *newCrypter, bool onlyWhileExpire) {
|
|
826
1032
|
if (m_hasFullWriteback) {
|
|
827
1033
|
return true;
|
|
828
1034
|
}
|
|
@@ -835,10 +1041,14 @@ bool MMKV::fullWriteback(AESCrypt *newCrypter) {
|
|
|
835
1041
|
}
|
|
836
1042
|
|
|
837
1043
|
if (unlikely(m_enableKeyExpire)) {
|
|
838
|
-
filterExpiredKeys();
|
|
1044
|
+
auto expiredCount = filterExpiredKeys();
|
|
1045
|
+
if (onlyWhileExpire && expiredCount == 0) {
|
|
1046
|
+
return true;
|
|
1047
|
+
}
|
|
839
1048
|
}
|
|
840
1049
|
|
|
841
|
-
|
|
1050
|
+
auto isEmpty = m_crypter ? m_dicCrypt->empty() : m_dic->empty();
|
|
1051
|
+
if (isEmpty) {
|
|
842
1052
|
clearAll();
|
|
843
1053
|
return true;
|
|
844
1054
|
}
|
|
@@ -1012,25 +1222,25 @@ static void fullWriteBackWholeData(MMBuffer allData, size_t totalSize, CodedOutp
|
|
|
1012
1222
|
if (allData.length() > 0) {
|
|
1013
1223
|
auto dataSize = CodedInputData(allData.getPtr(), allData.length()).readUInt32();
|
|
1014
1224
|
if (dataSize > 0) {
|
|
1015
|
-
auto dataPtr = (uint8_t *)allData.getPtr() + pbRawVarint32Size(dataSize);
|
|
1225
|
+
auto dataPtr = (uint8_t *) allData.getPtr() + pbRawVarint32Size(dataSize);
|
|
1016
1226
|
memcpy(output->curWritePointer(), dataPtr, dataSize);
|
|
1017
1227
|
output->seek(dataSize);
|
|
1018
1228
|
}
|
|
1019
1229
|
}
|
|
1020
|
-
[[maybe_unused]] auto writtenSize = (size_t)
|
|
1230
|
+
[[maybe_unused]] auto writtenSize = (size_t)(output->curWritePointer() - originOutputPtr);
|
|
1021
1231
|
assert(writtenSize == totalSize);
|
|
1022
1232
|
}
|
|
1023
1233
|
|
|
1024
1234
|
#ifndef MMKV_DISABLE_CRYPT
|
|
1025
|
-
bool MMKV::doFullWriteBack(pair<MMBuffer, size_t> prepared, AESCrypt *newCrypter) {
|
|
1235
|
+
bool MMKV::doFullWriteBack(pair<MMBuffer, size_t> prepared, AESCrypt *newCrypter, bool needSync) {
|
|
1026
1236
|
auto ptr = (uint8_t *) m_file->getMemory();
|
|
1027
1237
|
auto totalSize = prepared.second;
|
|
1028
|
-
#ifdef MMKV_IOS
|
|
1238
|
+
# ifdef MMKV_IOS
|
|
1029
1239
|
auto ret = guardForBackgroundWriting(ptr + Fixed32Size, totalSize);
|
|
1030
1240
|
if (!ret.first) {
|
|
1031
1241
|
return false;
|
|
1032
1242
|
}
|
|
1033
|
-
#endif
|
|
1243
|
+
# endif
|
|
1034
1244
|
|
|
1035
1245
|
uint8_t newIV[AES_KEY_LEN];
|
|
1036
1246
|
auto encrypter = (newCrypter == InvalidCryptPtr) ? nullptr : (newCrypter ? newCrypter : m_crypter);
|
|
@@ -1061,22 +1271,24 @@ bool MMKV::doFullWriteBack(pair<MMBuffer, size_t> prepared, AESCrypt *newCrypter
|
|
|
1061
1271
|
recaculateCRCDigestWithIV(nullptr);
|
|
1062
1272
|
}
|
|
1063
1273
|
m_hasFullWriteback = true;
|
|
1064
|
-
// make sure lastConfirmedMetaInfo is saved
|
|
1065
|
-
|
|
1274
|
+
// make sure lastConfirmedMetaInfo is saved if needed
|
|
1275
|
+
if (needSync) {
|
|
1276
|
+
sync(MMKV_SYNC);
|
|
1277
|
+
}
|
|
1066
1278
|
return true;
|
|
1067
1279
|
}
|
|
1068
1280
|
|
|
1069
1281
|
#else // MMKV_DISABLE_CRYPT
|
|
1070
1282
|
|
|
1071
|
-
bool MMKV::doFullWriteBack(pair<MMBuffer, size_t> prepared, AESCrypt
|
|
1283
|
+
bool MMKV::doFullWriteBack(pair<MMBuffer, size_t> prepared, AESCrypt *, bool needSync) {
|
|
1072
1284
|
auto ptr = (uint8_t *) m_file->getMemory();
|
|
1073
1285
|
auto totalSize = prepared.second;
|
|
1074
|
-
#ifdef MMKV_IOS
|
|
1286
|
+
# ifdef MMKV_IOS
|
|
1075
1287
|
auto ret = guardForBackgroundWriting(ptr + Fixed32Size, totalSize);
|
|
1076
1288
|
if (!ret.first) {
|
|
1077
1289
|
return false;
|
|
1078
1290
|
}
|
|
1079
|
-
#endif
|
|
1291
|
+
# endif
|
|
1080
1292
|
|
|
1081
1293
|
delete m_output;
|
|
1082
1294
|
m_output = new CodedOutputData(ptr + Fixed32Size, m_file->getFileSize() - Fixed32Size);
|
|
@@ -1091,8 +1303,10 @@ bool MMKV::doFullWriteBack(pair<MMBuffer, size_t> prepared, AESCrypt *) {
|
|
|
1091
1303
|
m_actualSize = totalSize;
|
|
1092
1304
|
recaculateCRCDigestWithIV(nullptr);
|
|
1093
1305
|
m_hasFullWriteback = true;
|
|
1094
|
-
// make sure lastConfirmedMetaInfo is saved
|
|
1095
|
-
|
|
1306
|
+
// make sure lastConfirmedMetaInfo is saved if needed
|
|
1307
|
+
if (needSync) {
|
|
1308
|
+
sync(MMKV_SYNC);
|
|
1309
|
+
}
|
|
1096
1310
|
return true;
|
|
1097
1311
|
}
|
|
1098
1312
|
#endif // MMKV_DISABLE_CRYPT
|
|
@@ -1102,6 +1316,10 @@ bool MMKV::reKey(const string &cryptKey) {
|
|
|
1102
1316
|
SCOPED_LOCK(m_lock);
|
|
1103
1317
|
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1104
1318
|
checkLoadData();
|
|
1319
|
+
if (!isFileValid()) {
|
|
1320
|
+
MMKVWarning("[%s] file not valid", m_mmapID.c_str());
|
|
1321
|
+
return false;
|
|
1322
|
+
}
|
|
1105
1323
|
|
|
1106
1324
|
bool ret = false;
|
|
1107
1325
|
if (m_crypter) {
|
|
@@ -1167,11 +1385,15 @@ void MMKV::trim() {
|
|
|
1167
1385
|
MMKVInfo("prepare to trim %s", m_mmapID.c_str());
|
|
1168
1386
|
|
|
1169
1387
|
checkLoadData();
|
|
1388
|
+
if (!isFileValid()) {
|
|
1389
|
+
MMKVWarning("[%s] file not valid", m_mmapID.c_str());
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1170
1392
|
|
|
1171
1393
|
if (m_actualSize == 0) {
|
|
1172
1394
|
clearAll();
|
|
1173
1395
|
return;
|
|
1174
|
-
} else if (m_file->getFileSize() <=
|
|
1396
|
+
} else if (m_file->getFileSize() <= m_expectedCapacity) {
|
|
1175
1397
|
return;
|
|
1176
1398
|
}
|
|
1177
1399
|
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
@@ -1182,7 +1404,7 @@ void MMKV::trim() {
|
|
|
1182
1404
|
while (fileSize > (m_actualSize + Fixed32Size) * 2) {
|
|
1183
1405
|
fileSize /= 2;
|
|
1184
1406
|
}
|
|
1185
|
-
fileSize = std::max<size_t>(fileSize,
|
|
1407
|
+
fileSize = std::max<size_t>(fileSize, m_expectedCapacity);
|
|
1186
1408
|
if (oldSize == fileSize) {
|
|
1187
1409
|
MMKVInfo("there's no need to trim %s with size %zu, actualSize %zu", m_mmapID.c_str(), fileSize, m_actualSize);
|
|
1188
1410
|
return;
|
|
@@ -1202,18 +1424,25 @@ void MMKV::trim() {
|
|
|
1202
1424
|
MMKVInfo("finish trim %s from %zu to %zu", m_mmapID.c_str(), oldSize, fileSize);
|
|
1203
1425
|
}
|
|
1204
1426
|
|
|
1205
|
-
void MMKV::clearAll() {
|
|
1427
|
+
void MMKV::clearAll(bool keepSpace) {
|
|
1206
1428
|
MMKVInfo("cleaning all key-values from [%s]", m_mmapID.c_str());
|
|
1207
1429
|
SCOPED_LOCK(m_lock);
|
|
1208
1430
|
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1209
1431
|
|
|
1210
1432
|
checkLoadData();
|
|
1433
|
+
if (!isFileValid()) {
|
|
1434
|
+
MMKVWarning("[%s] file not valid", m_mmapID.c_str());
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1211
1437
|
|
|
1212
|
-
if (m_file->getFileSize() ==
|
|
1438
|
+
if (m_file->getFileSize() == m_expectedCapacity && m_actualSize == 0) {
|
|
1213
1439
|
MMKVInfo("nothing to clear for [%s]", m_mmapID.c_str());
|
|
1214
1440
|
return;
|
|
1215
1441
|
}
|
|
1216
|
-
|
|
1442
|
+
|
|
1443
|
+
if (!keepSpace) {
|
|
1444
|
+
m_file->truncate(m_expectedCapacity);
|
|
1445
|
+
}
|
|
1217
1446
|
|
|
1218
1447
|
#ifndef MMKV_DISABLE_CRYPT
|
|
1219
1448
|
uint8_t newIV[AES_KEY_LEN];
|
|
@@ -1225,9 +1454,10 @@ void MMKV::clearAll() {
|
|
|
1225
1454
|
#else
|
|
1226
1455
|
writeActualSize(0, 0, nullptr, IncreaseSequence);
|
|
1227
1456
|
#endif
|
|
1457
|
+
|
|
1228
1458
|
m_metaFile->msync(MMKV_SYNC);
|
|
1229
1459
|
|
|
1230
|
-
clearMemoryCache();
|
|
1460
|
+
clearMemoryCache(keepSpace);
|
|
1231
1461
|
loadFromFile();
|
|
1232
1462
|
}
|
|
1233
1463
|
|
|
@@ -1275,6 +1505,54 @@ bool MMKV::isFileValid(const string &mmapID, MMKVPath_t *relatePath) {
|
|
|
1275
1505
|
}
|
|
1276
1506
|
}
|
|
1277
1507
|
|
|
1508
|
+
bool MMKV::removeStorage(const std::string &mmapID, MMKVPath_t *relatePath) {
|
|
1509
|
+
auto mmapKey = mmapedKVKey(mmapID, relatePath);
|
|
1510
|
+
#ifdef MMKV_ANDROID
|
|
1511
|
+
auto &realID = mmapKey; // historically Android mistakenly use mmapKey as mmapID
|
|
1512
|
+
#else
|
|
1513
|
+
auto &realID = mmapID;
|
|
1514
|
+
#endif
|
|
1515
|
+
MMKVDebug("mmapKey %s", mmapKey.c_str());
|
|
1516
|
+
|
|
1517
|
+
MMKVPath_t kvPath = mappedKVPathWithID(realID, MMKV_SINGLE_PROCESS, relatePath);
|
|
1518
|
+
if (!isFileExist(kvPath)) {
|
|
1519
|
+
MMKVWarning("file not exist %s", kvPath.c_str());
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
MMKVPath_t crcPath = crcPathWithID(realID, MMKV_SINGLE_PROCESS, relatePath);
|
|
1523
|
+
if (!isFileExist(crcPath)) {
|
|
1524
|
+
MMKVWarning("file not exist %s", crcPath.c_str());
|
|
1525
|
+
return false;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
MMKVInfo("remove storage [%s]", mmapID.c_str());
|
|
1529
|
+
SCOPED_LOCK(g_instanceLock);
|
|
1530
|
+
|
|
1531
|
+
File crcFile(crcPath, OpenFlag::ReadOnly);
|
|
1532
|
+
if (!crcFile.isFileValid()) {
|
|
1533
|
+
return false;
|
|
1534
|
+
}
|
|
1535
|
+
FileLock fileLock(crcFile.getFd());
|
|
1536
|
+
InterProcessLock lock(&fileLock, ExclusiveLockType);
|
|
1537
|
+
SCOPED_LOCK(&lock);
|
|
1538
|
+
|
|
1539
|
+
auto itr = g_instanceDic->find(mmapKey);
|
|
1540
|
+
if (itr != g_instanceDic->end()) {
|
|
1541
|
+
itr->second->close();
|
|
1542
|
+
// itr is not valid after this
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
#ifndef MMKV_WIN32
|
|
1546
|
+
::unlink(kvPath.c_str());
|
|
1547
|
+
::unlink(crcPath.c_str());
|
|
1548
|
+
#else
|
|
1549
|
+
DeleteFile(kvPath.c_str());
|
|
1550
|
+
DeleteFile(crcPath.c_str());
|
|
1551
|
+
#endif
|
|
1552
|
+
|
|
1553
|
+
return true;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1278
1556
|
// ---- auto expire ----
|
|
1279
1557
|
|
|
1280
1558
|
uint32_t MMKV::getCurrentTimeInSecond() {
|
|
@@ -1311,6 +1589,15 @@ bool MMKV::enableAutoKeyExpire(uint32_t expiredInSeconds) {
|
|
|
1311
1589
|
SCOPED_LOCK(m_lock);
|
|
1312
1590
|
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1313
1591
|
checkLoadData();
|
|
1592
|
+
if (!isFileValid() || !m_metaFile->isFileValid()) {
|
|
1593
|
+
MMKVWarning("[%s] file not valid", m_mmapID.c_str());
|
|
1594
|
+
return false;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
if (m_enableCompareBeforeSet) {
|
|
1598
|
+
MMKVError("enableCompareBeforeSet will be invalid when Expiration is on");
|
|
1599
|
+
m_enableCompareBeforeSet = false;
|
|
1600
|
+
}
|
|
1314
1601
|
|
|
1315
1602
|
if (m_expiredInSeconds != expiredInSeconds) {
|
|
1316
1603
|
MMKVInfo("expiredInSeconds: %u", expiredInSeconds);
|
|
@@ -1327,7 +1614,7 @@ bool MMKV::enableAutoKeyExpire(uint32_t expiredInSeconds) {
|
|
|
1327
1614
|
m_metaInfo->setFlag(MMKVMetaInfo::EnableKeyExipre);
|
|
1328
1615
|
m_metaInfo->m_version = MMKVVersionFlag;
|
|
1329
1616
|
|
|
1330
|
-
if (m_file->getFileSize() ==
|
|
1617
|
+
if (m_file->getFileSize() == m_expectedCapacity && m_actualSize == 0) {
|
|
1331
1618
|
MMKVInfo("file is new, don't need a full writeback [%s], just update meta file", m_mmapID.c_str());
|
|
1332
1619
|
writeActualSize(0, 0, nullptr, IncreaseSequence);
|
|
1333
1620
|
m_metaFile->msync(MMKV_SYNC);
|
|
@@ -1337,7 +1624,7 @@ bool MMKV::enableAutoKeyExpire(uint32_t expiredInSeconds) {
|
|
|
1337
1624
|
MMKVVector vec;
|
|
1338
1625
|
auto packKeyValue = [&](const MMKVKey_t &key, const MMBuffer &value) {
|
|
1339
1626
|
MMBuffer data(value.length() + Fixed32Size);
|
|
1340
|
-
auto ptr = (uint8_t *)data.getPtr();
|
|
1627
|
+
auto ptr = (uint8_t *) data.getPtr();
|
|
1341
1628
|
memcpy(ptr, value.getPtr(), value.length());
|
|
1342
1629
|
memcpy(ptr + value.length(), &time, Fixed32Size);
|
|
1343
1630
|
vec.emplace_back(key, std::move(data));
|
|
@@ -1370,6 +1657,10 @@ bool MMKV::disableAutoKeyExpire() {
|
|
|
1370
1657
|
SCOPED_LOCK(m_lock);
|
|
1371
1658
|
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1372
1659
|
checkLoadData();
|
|
1660
|
+
if (!isFileValid() || !m_metaFile->isFileValid()) {
|
|
1661
|
+
MMKVWarning("[%s] file not valid", m_mmapID.c_str());
|
|
1662
|
+
return false;
|
|
1663
|
+
}
|
|
1373
1664
|
|
|
1374
1665
|
m_expiredInSeconds = 0;
|
|
1375
1666
|
m_enableKeyExpire = false;
|
|
@@ -1381,7 +1672,7 @@ bool MMKV::disableAutoKeyExpire() {
|
|
|
1381
1672
|
m_metaInfo->unsetFlag(MMKVMetaInfo::EnableKeyExipre);
|
|
1382
1673
|
m_metaInfo->m_version = MMKVVersionFlag;
|
|
1383
1674
|
|
|
1384
|
-
if (m_file->getFileSize() ==
|
|
1675
|
+
if (m_file->getFileSize() == m_expectedCapacity && m_actualSize == 0) {
|
|
1385
1676
|
MMKVInfo("file is new, don't need a full write-back [%s], just update meta file", m_mmapID.c_str());
|
|
1386
1677
|
writeActualSize(0, 0, nullptr, IncreaseSequence);
|
|
1387
1678
|
m_metaFile->msync(MMKV_SYNC);
|
|
@@ -1392,7 +1683,7 @@ bool MMKV::disableAutoKeyExpire() {
|
|
|
1392
1683
|
auto packKeyValue = [&](const MMKVKey_t &key, const MMBuffer &value) {
|
|
1393
1684
|
assert(value.length() >= Fixed32Size);
|
|
1394
1685
|
MMBuffer data(value.length() - Fixed32Size);
|
|
1395
|
-
auto ptr = (uint8_t *)data.getPtr();
|
|
1686
|
+
auto ptr = (uint8_t *) data.getPtr();
|
|
1396
1687
|
memcpy(ptr, value.getPtr(), value.length() - Fixed32Size);
|
|
1397
1688
|
vec.emplace_back(key, std::move(data));
|
|
1398
1689
|
};
|
|
@@ -1425,7 +1716,7 @@ uint32_t MMKV::getExpireTimeForKey(MMKVKey_t key) {
|
|
|
1425
1716
|
SCOPED_LOCK(m_sharedProcessLock);
|
|
1426
1717
|
checkLoadData();
|
|
1427
1718
|
|
|
1428
|
-
if (!m_enableKeyExpire ||
|
|
1719
|
+
if (!m_enableKeyExpire || mmkv_key_length(key) == 0) {
|
|
1429
1720
|
return 0;
|
|
1430
1721
|
}
|
|
1431
1722
|
auto raw = getRawDataForKey(key);
|
|
@@ -1433,8 +1724,8 @@ uint32_t MMKV::getExpireTimeForKey(MMKVKey_t key) {
|
|
|
1433
1724
|
if (raw.length() < Fixed32Size) {
|
|
1434
1725
|
return 0;
|
|
1435
1726
|
}
|
|
1436
|
-
auto ptr = (const uint8_t *)raw.getPtr() + raw.length() - Fixed32Size;
|
|
1437
|
-
auto time = *(const uint32_t *)ptr;
|
|
1727
|
+
auto ptr = (const uint8_t *) raw.getPtr() + raw.length() - Fixed32Size;
|
|
1728
|
+
auto time = *(const uint32_t *) ptr;
|
|
1438
1729
|
return time;
|
|
1439
1730
|
}
|
|
1440
1731
|
|
|
@@ -1450,8 +1741,8 @@ mmkv::MMBuffer MMKV::getDataWithoutMTimeForKey(MMKVKey_t key) {
|
|
|
1450
1741
|
}
|
|
1451
1742
|
auto newLength = raw.length() - Fixed32Size;
|
|
1452
1743
|
if (m_enableKeyExpire) {
|
|
1453
|
-
auto ptr = (const uint8_t *)raw.getPtr() + newLength;
|
|
1454
|
-
auto time = *(const uint32_t *)ptr;
|
|
1744
|
+
auto ptr = (const uint8_t *) raw.getPtr() + newLength;
|
|
1745
|
+
auto time = *(const uint32_t *) ptr;
|
|
1455
1746
|
if (time != ExpireNever && time <= getCurrentTimeInSecond()) {
|
|
1456
1747
|
#ifdef MMKV_APPLE
|
|
1457
1748
|
MMKVInfo("deleting expired key [%@] in mmkv [%s], due date %u", key, m_mmapID.c_str(), time);
|
|
@@ -1465,35 +1756,38 @@ mmkv::MMBuffer MMKV::getDataWithoutMTimeForKey(MMKVKey_t key) {
|
|
|
1465
1756
|
return MMBuffer(std::move(raw), newLength);
|
|
1466
1757
|
}
|
|
1467
1758
|
|
|
1468
|
-
#define NOOP ((void)0)
|
|
1759
|
+
#define NOOP ((void) 0)
|
|
1469
1760
|
|
|
1470
1761
|
size_t MMKV::filterExpiredKeys() {
|
|
1471
1762
|
if (!m_enableKeyExpire || (m_crypter ? m_dicCrypt->empty() : m_dic->empty())) {
|
|
1472
1763
|
return 0;
|
|
1473
1764
|
}
|
|
1765
|
+
SCOPED_LOCK(m_sharedProcessLock);
|
|
1766
|
+
|
|
1474
1767
|
auto now = getCurrentTimeInSecond();
|
|
1475
|
-
MMKVInfo("filtering expired keys inside [%s] now: %u, m_expiredInSeconds: %u", m_mmapID.c_str(), now,
|
|
1768
|
+
MMKVInfo("filtering expired keys inside [%s] now: %u, m_expiredInSeconds: %u", m_mmapID.c_str(), now,
|
|
1769
|
+
m_expiredInSeconds);
|
|
1476
1770
|
|
|
1477
1771
|
size_t count = 0;
|
|
1478
|
-
auto basePtr = (uint8_t *)(m_file->getMemory()) + Fixed32Size;
|
|
1772
|
+
auto basePtr = (uint8_t *) (m_file->getMemory()) + Fixed32Size;
|
|
1479
1773
|
#ifndef MMKV_DISABLE_CRYPT
|
|
1480
1774
|
if (m_crypter) {
|
|
1481
1775
|
for (auto itr = m_dicCrypt->begin(); itr != m_dicCrypt->end(); NOOP) {
|
|
1482
1776
|
auto &kvHolder = itr->second;
|
|
1483
1777
|
assert(kvHolder.realValueSize() >= Fixed32Size);
|
|
1484
1778
|
auto buffer = kvHolder.toMMBuffer(basePtr, m_crypter);
|
|
1485
|
-
auto ptr = (uint8_t*) buffer.getPtr();
|
|
1779
|
+
auto ptr = (uint8_t *) buffer.getPtr();
|
|
1486
1780
|
ptr += buffer.length() - Fixed32Size;
|
|
1487
|
-
auto time = *(const uint32_t *)ptr;
|
|
1781
|
+
auto time = *(const uint32_t *) ptr;
|
|
1488
1782
|
if (time != ExpireNever && time <= now) {
|
|
1489
1783
|
auto oldKey = itr->first;
|
|
1490
1784
|
itr = m_dicCrypt->erase(itr);
|
|
1491
|
-
#ifdef MMKV_APPLE
|
|
1785
|
+
# ifdef MMKV_APPLE
|
|
1492
1786
|
MMKVInfo("deleting expired key [%@], due date %u", oldKey, time);
|
|
1493
1787
|
[oldKey release];
|
|
1494
|
-
#else
|
|
1788
|
+
# else
|
|
1495
1789
|
MMKVInfo("deleting expired key [%s], due date %u", oldKey.c_str(), time);
|
|
1496
|
-
#endif
|
|
1790
|
+
# endif
|
|
1497
1791
|
count++;
|
|
1498
1792
|
} else {
|
|
1499
1793
|
itr++;
|
|
@@ -1507,7 +1801,7 @@ size_t MMKV::filterExpiredKeys() {
|
|
|
1507
1801
|
assert(kvHolder.valueSize >= Fixed32Size);
|
|
1508
1802
|
auto ptr = basePtr + kvHolder.offset + kvHolder.computedKVSize;
|
|
1509
1803
|
ptr += kvHolder.valueSize - Fixed32Size;
|
|
1510
|
-
auto time = *(const uint32_t *)ptr;
|
|
1804
|
+
auto time = *(const uint32_t *) ptr;
|
|
1511
1805
|
if (time != ExpireNever && time <= now) {
|
|
1512
1806
|
auto oldKey = itr->first;
|
|
1513
1807
|
itr = m_dic->erase(itr);
|
|
@@ -1523,8 +1817,40 @@ size_t MMKV::filterExpiredKeys() {
|
|
|
1523
1817
|
}
|
|
1524
1818
|
}
|
|
1525
1819
|
}
|
|
1526
|
-
|
|
1820
|
+
if (count != 0) {
|
|
1821
|
+
MMKVInfo("deleted %zu expired keys inside [%s]", count, m_mmapID.c_str());
|
|
1822
|
+
}
|
|
1527
1823
|
return count;
|
|
1528
1824
|
}
|
|
1529
1825
|
|
|
1826
|
+
bool MMKV::enableCompareBeforeSet() {
|
|
1827
|
+
MMKVInfo("enableCompareBeforeSet for [%s]", m_mmapID.c_str());
|
|
1828
|
+
SCOPED_LOCK(m_lock);
|
|
1829
|
+
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1830
|
+
|
|
1831
|
+
assert(!m_enableKeyExpire && "enableCompareBeforeSet is invalid when Expiration is on");
|
|
1832
|
+
assert(!m_dicCrypt && "enableCompareBeforeSet is invalid when key encryption is on");
|
|
1833
|
+
if (m_enableKeyExpire || m_dicCrypt) {
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
m_enableCompareBeforeSet = true;
|
|
1838
|
+
return true;
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
bool MMKV::disableCompareBeforeSet() {
|
|
1842
|
+
MMKVInfo("disableCompareBeforeSet for [%s]", m_mmapID.c_str());
|
|
1843
|
+
SCOPED_LOCK(m_lock);
|
|
1844
|
+
SCOPED_LOCK(m_exclusiveProcessLock);
|
|
1845
|
+
|
|
1846
|
+
assert(!m_enableKeyExpire && "disableCompareBeforeSet is invalid when Expiration is on");
|
|
1847
|
+
assert(!m_dicCrypt && "disableCompareBeforeSet is invalid when key encryption is on");
|
|
1848
|
+
if (m_enableKeyExpire || m_dicCrypt) {
|
|
1849
|
+
return false;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
m_enableCompareBeforeSet = false;
|
|
1853
|
+
return true;
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1530
1856
|
MMKV_NAMESPACE_END
|