| 905 | #pragma endregion |
| 906 | |
| 907 | bool expandMutation(MutationRef& m, StorageCacheData::VersionedData const& data, KeyRef eagerTrustedEnd, Arena& ar) { |
| 908 | // After this function call, m should be copied into an arena immediately (before modifying data, cacheRanges, or |
| 909 | // eager) |
| 910 | if (m.type == MutationRef::ClearRange) { |
| 911 | // Expand the clear |
| 912 | const auto& d = data.atLatest(); |
| 913 | |
| 914 | // If another clear overlaps the beginning of this one, engulf it |
| 915 | auto i = d.lastLess(m.param1); |
| 916 | if (i && i->isClearTo() && i->getEndKey() >= m.param1) |
| 917 | m.param1 = i.key(); |
| 918 | |
| 919 | // If another clear overlaps the end of this one, engulf it; otherwise expand |
| 920 | i = d.lastLessOrEqual(m.param2); |
| 921 | if (i && i->isClearTo() && i->getEndKey() >= m.param2) { |
| 922 | m.param2 = i->getEndKey(); |
| 923 | } else { |
| 924 | // Expand to the next set or clear (from storage or latestVersion), and if it |
| 925 | // is a clear, engulf it as well |
| 926 | i = d.lower_bound(m.param2); |
| 927 | // TODO check if the following is correct |
| 928 | KeyRef endKey = eagerTrustedEnd; |
| 929 | if (!i || endKey < i.key()) |
| 930 | m.param2 = endKey; |
| 931 | else if (i->isClearTo()) |
| 932 | m.param2 = i->getEndKey(); |
| 933 | else |
| 934 | m.param2 = i.key(); |
| 935 | } |
| 936 | } else if (m.type != MutationRef::SetValue && (m.type)) { |
| 937 | |
| 938 | Optional<StringRef> oldVal; |
| 939 | auto it = data.atLatest().lastLessOrEqual(m.param1); |
| 940 | if (it != data.atLatest().end() && it->isValue() && it.key() == m.param1) |
| 941 | oldVal = it->getValue(); |
| 942 | else if (it != data.atLatest().end() && it->isClearTo() && it->getEndKey() > m.param1) { |
| 943 | CODE_PROBE(true, "Atomic op right after a clear."); |
| 944 | } |
| 945 | |
| 946 | switch (m.type) { |
| 947 | case MutationRef::AddValue: |
| 948 | m.param2 = doLittleEndianAdd(oldVal, m.param2, ar); |
| 949 | break; |
| 950 | case MutationRef::And: |
| 951 | m.param2 = doAnd(oldVal, m.param2, ar); |
| 952 | break; |
| 953 | case MutationRef::Or: |
| 954 | m.param2 = doOr(oldVal, m.param2, ar); |
| 955 | break; |
| 956 | case MutationRef::Xor: |
| 957 | m.param2 = doXor(oldVal, m.param2, ar); |
| 958 | break; |
| 959 | case MutationRef::AppendIfFits: |
| 960 | m.param2 = doAppendIfFits(oldVal, m.param2, ar); |
| 961 | break; |
| 962 | case MutationRef::Max: |
| 963 | m.param2 = doMax(oldVal, m.param2, ar); |
| 964 | break; |
no test coverage detected