* Reinsert or remove an item during region reclaim. * * This function evaluates an item found in a reclaiming region and decides * whether to: * 1. do nothing if item has been overwritten/replaced, or key not in index. * 2. remove the item from index on reinsertion error, expiry or cheksum error. * 3. reinsert the item if the reinsertion policy decides to. * 4. evict the item. * * @pa
| 1136 | * INVALIDATED, NOT_FOUND, or CORRUPTED. |
| 1137 | */ |
| 1138 | AllocatorApiResult BlockCache::reinsertOrRemoveItem( |
| 1139 | HashedKey hk, |
| 1140 | BufferView value, |
| 1141 | uint32_t entrySize, |
| 1142 | RelAddress currAddr, |
| 1143 | const EntryDesc& entryDesc) { |
| 1144 | // Remove the key from index and return the correct result. |
| 1145 | auto removeItem = [this, hk, currAddr](bool expired) { |
| 1146 | if (index_->removeIfMatch(hk.keyHash(), encodeRelAddress(currAddr))) { |
| 1147 | if (expired) { |
| 1148 | evictionExpiredCount_.inc(); |
| 1149 | return AllocatorApiResult::EXPIRED; |
| 1150 | } |
| 1151 | return AllocatorApiResult::EVICTED; |
| 1152 | } |
| 1153 | return AllocatorApiResult::REMOVED; |
| 1154 | }; |
| 1155 | |
| 1156 | const auto lr = index_->peek(hk.keyHash()); |
| 1157 | if (!lr.found() || decodeRelAddress(lr.address()) != currAddr) { |
| 1158 | evictionLookupMissCounter_.inc(); |
| 1159 | // Either item is not in index (NOT_FOUND) or the time has been |
| 1160 | // replaced by a newer item hence the current item is invalidated |
| 1161 | // (INVALIDATED). |
| 1162 | auto eventRes = !lr.found() ? AllocatorApiResult::NOT_FOUND |
| 1163 | : AllocatorApiResult::INVALIDATED; |
| 1164 | recordEvent(hk.key(), AllocatorApiEvent::NVM_REINSERT, eventRes, entrySize); |
| 1165 | return AllocatorApiResult::REMOVED; |
| 1166 | } |
| 1167 | |
| 1168 | try { |
| 1169 | if (checkExpired_ && checkExpired_(value)) { |
| 1170 | recordEvent(hk.key(), AllocatorApiEvent::NVM_REINSERT, |
| 1171 | AllocatorApiResult::EXPIRED, entrySize); |
| 1172 | return removeItem(true); |
| 1173 | } |
| 1174 | |
| 1175 | if (!reinsertionPolicy_ || |
| 1176 | !reinsertionPolicy_->shouldReinsert(hk.key(), toStringPiece(value))) { |
| 1177 | recordEvent(hk.key(), AllocatorApiEvent::NVM_REINSERT, |
| 1178 | AllocatorApiResult::REJECTED, entrySize); |
| 1179 | return removeItem(false); |
| 1180 | } |
| 1181 | } catch (const std::exception& e) { |
| 1182 | XLOGF(ERR, "Exception in reinsertOrRemoveItem: {}", e.what()); |
| 1183 | recordEvent(hk.key(), AllocatorApiEvent::NVM_REINSERT, |
| 1184 | AllocatorApiResult::CORRUPTED, entrySize); |
| 1185 | return AllocatorApiResult::CORRUPTED; |
| 1186 | } |
| 1187 | |
| 1188 | // Validate checksum as we want to reinsert the item |
| 1189 | if (checksumData_ && entryDesc.cs != checksum(value)) { |
| 1190 | // We do not need to abort here since the EntryDesc checksum was good, so |
| 1191 | // we can safely proceed to read the next entry. |
| 1192 | XLOGF(ERR, |
| 1193 | "Item value checksum mismatch in reinsertOrRemoveItem(). " |
| 1194 | "Item is likely corrupted. Item will not be reinserted. " |
| 1195 | "We will continue evaluating remaining items in the region." |
nothing calls this directly
no test coverage detected