Applies a write mutation (SetValue or ClearRange) to the in-memory versioned data structure
| 993 | |
| 994 | // Applies a write mutation (SetValue or ClearRange) to the in-memory versioned data structure |
| 995 | void StorageCacheData::applyMutation(MutationRef const& m, Arena& arena, StorageCacheData::VersionedData& data) { |
| 996 | // m is expected to be in arena already |
| 997 | // Clear split keys are added to arena |
| 998 | |
| 999 | if (m.type == MutationRef::SetValue) { |
| 1000 | auto prev = data.atLatest().lastLessOrEqual(m.param1); |
| 1001 | if (prev && prev->isClearTo() && prev->getEndKey() > m.param1) { |
| 1002 | ASSERT(prev.key() <= m.param1); |
| 1003 | KeyRef end = prev->getEndKey(); |
| 1004 | // TODO double check if the insert version of the previous clear needs to be preserved for the "left half", |
| 1005 | // insert() invalidates prev, so prev.key() is not safe to pass to it by reference |
| 1006 | data.insert(KeyRef(prev.key()), |
| 1007 | ValueOrClearToRef::clearTo(m.param1), |
| 1008 | prev.insertVersion()); // overwritten by below insert if empty |
| 1009 | //TraceEvent(SevDebug, "ApplyMutationClearTo") |
| 1010 | //.detail("Key1", prev.key()) |
| 1011 | //.detail("Key2",m.param1) |
| 1012 | //.detail("Version1", prev.insertVersion()); |
| 1013 | KeyRef nextKey = keyAfter(m.param1, arena); |
| 1014 | if (end != nextKey) { |
| 1015 | ASSERT(end > nextKey); |
| 1016 | // TODO double check if it's okay to let go of the the insert version of the "right half" |
| 1017 | // FIXME: This copy is technically an asymptotic problem, definitely a waste of memory (copy of keyAfter |
| 1018 | // is a waste, but not asymptotic) |
| 1019 | data.insert(nextKey, ValueOrClearToRef::clearTo(KeyRef(arena, end))); |
| 1020 | //TraceEvent(SevDebug, "ApplyMutationClearTo2") |
| 1021 | //.detail("K1", nextKey) |
| 1022 | //.detail("K2", end) |
| 1023 | //.detail("V", data.latestVersion); |
| 1024 | } |
| 1025 | } |
| 1026 | data.insert(m.param1, ValueOrClearToRef::value(m.param2)); |
| 1027 | //TraceEvent(SevDebug, "ApplyMutation") |
| 1028 | // .detail("Key", m.param1) |
| 1029 | // .detail("Value",m.param2) |
| 1030 | // .detail("Version", data.latestVersion); |
| 1031 | } else if (m.type == MutationRef::ClearRange) { |
| 1032 | data.erase(m.param1, m.param2); |
| 1033 | ASSERT(m.param2 > m.param1); |
| 1034 | ASSERT(!data.isClearContaining(data.atLatest(), m.param1)); |
| 1035 | data.insert(m.param1, ValueOrClearToRef::clearTo(m.param2)); |
| 1036 | //TraceEvent(SevDebug, "ApplyMutationClearTo3") |
| 1037 | // .detail("Key21", m.param1) |
| 1038 | // .detail("Key22", m.param2) |
| 1039 | // .detail("V2", data.latestVersion); |
| 1040 | } |
| 1041 | } |
| 1042 | |
| 1043 | template <class T> |
| 1044 | void addMutation(T& target, Version version, MutationRef const& mutation) { |
no test coverage detected