Parse the kv pair (version, serialized_mutation), which are the results parsed from log file, into (version, ) pair; Put the parsed versioned mutations into *pkvOps. Input key: [commitVersion_of_the_mutation_batch:uint64_t]; Input value: [includeVersion:uint64_t][val_length:uint32_t][encoded_list_of_mutations], where includeVersion is the serialized version in the batch commit
| 1084 | // [mutation1][mutation2]...[mutationk], where |
| 1085 | // a mutation is encoded as [type:uint32_t][keyLength:uint32_t][valueLength:uint32_t][keyContent][valueContent] |
| 1086 | void _parseSerializedMutation(KeyRangeMap<Version>* pRangeVersions, |
| 1087 | std::map<LoadingParam, VersionedMutationsMap>::iterator kvOpsIter, |
| 1088 | SerializedMutationListMap* pmutationMap, |
| 1089 | std::map<LoadingParam, SampledMutationsVec>::iterator samplesIter, |
| 1090 | LoaderCounters* cc, |
| 1091 | const RestoreAsset& asset) { |
| 1092 | VersionedMutationsMap& kvOps = kvOpsIter->second; |
| 1093 | SampledMutationsVec& samples = samplesIter->second; |
| 1094 | SerializedMutationListMap& mutationMap = *pmutationMap; |
| 1095 | |
| 1096 | TraceEvent(SevFRMutationInfo, "FastRestoreLoaderParseSerializedLogMutation") |
| 1097 | .detail("BatchIndex", asset.batchIndex) |
| 1098 | .detail("RestoreAsset", asset.toString()); |
| 1099 | |
| 1100 | Arena tempArena; |
| 1101 | for (auto& m : mutationMap) { |
| 1102 | StringRef k = m.first.contents(); |
| 1103 | StringRef val = m.second.first.contents(); |
| 1104 | |
| 1105 | StringRefReader kReader(k, restore_corrupted_data()); |
| 1106 | uint64_t commitVersion = kReader.consume<uint64_t>(); // Consume little Endian data |
| 1107 | // We have already filter the commit not in [beginVersion, endVersion) when we concatenate kv pair in log file |
| 1108 | ASSERT_WE_THINK(asset.isInVersionRange(commitVersion)); |
| 1109 | |
| 1110 | StringRefReader vReader(val, restore_corrupted_data()); |
| 1111 | vReader.consume<uint64_t>(); // Consume the includeVersion |
| 1112 | // TODO(xumengpanda): verify the protocol version is compatible and raise error if needed |
| 1113 | |
| 1114 | // Parse little endian value, confirmed it is correct! |
| 1115 | uint32_t val_length_decoded = vReader.consume<uint32_t>(); |
| 1116 | ASSERT(val_length_decoded == val.size() - sizeof(uint64_t) - sizeof(uint32_t)); |
| 1117 | |
| 1118 | int sub = 0; |
| 1119 | while (1) { |
| 1120 | // stop when reach the end of the string |
| 1121 | if (vReader.eof()) { //|| *reader.rptr == 0xFF |
| 1122 | break; |
| 1123 | } |
| 1124 | |
| 1125 | uint32_t type = vReader.consume<uint32_t>(); |
| 1126 | uint32_t kLen = vReader.consume<uint32_t>(); |
| 1127 | uint32_t vLen = vReader.consume<uint32_t>(); |
| 1128 | const uint8_t* k = vReader.consume(kLen); |
| 1129 | const uint8_t* v = vReader.consume(vLen); |
| 1130 | |
| 1131 | MutationRef mutation((MutationRef::Type)type, KeyRef(k, kLen), KeyRef(v, vLen)); |
| 1132 | // Should this mutation be skipped? |
| 1133 | // Skip mutation whose commitVesion < range kv's version |
| 1134 | if (logMutationTooOld(pRangeVersions, mutation, commitVersion)) { |
| 1135 | cc->oldLogMutations += 1; |
| 1136 | continue; |
| 1137 | } |
| 1138 | |
| 1139 | if (mutation.param1 >= asset.range.end || |
| 1140 | (isRangeMutation(mutation) && mutation.param2 < asset.range.begin) || |
| 1141 | (!isRangeMutation(mutation) && mutation.param1 < asset.range.begin)) { |
| 1142 | continue; |
| 1143 | } |
no test coverage detected