in cachelib/compact_cache/CCacheVariableLruBucket.h [624:694]
static void checkBucketConsistency(Bucket* bucket) {
EntryHandle handle = first(bucket);
size_t totalSize = 0;
size_t nEntries = 0;
bool headerOffsetError = false;
/* Check that the data part does not overlap the entry headers. */
XDCHECK_GE(reinterpret_cast<uintptr_t>(getFirstEntryData(bucket)),
reinterpret_cast<uintptr_t>(
getEntryHeader(bucket, bucket->numEntries)));
/* Keep track of the EntryData's offsets and sizes as we see then
* when iterating on the EntryHdr headers. We will later use this to
* check that the EntryData objects are contiguous. */
using EntryInfo = std::pair<EntryDataOffset, EntryDataSize>;
std::vector<EntryInfo> entryDataSeen;
/* Iterate on the EntryHdr headers. */
while (handle) {
EntryData* entryData = getEntryData(handle.bucket_, handle.pos_);
totalSize += handle.size() + sizeof(EntryData);
/* The offset headers of the entries we are seeing should match
* their order. */
if (entryData->headerIndex != nEntries) {
headerOffsetError = true;
}
EntryHdr* entryHeader = getEntryHeader(bucket, handle.pos_);
EntryDataOffset dataOffset = entryHeader->dataOffset;
EntryDataSize dataSize = entryHeader->dataSize;
entryDataSeen.push_back(std::make_pair(dataOffset, dataSize));
handle.next();
nEntries++;
}
/* Sort entryDataSeen by offset, in increasing order. */
auto compareFn = [](const EntryInfo& a, const EntryInfo& b) -> bool {
return a.first < b.first;
};
std::sort(entryDataSeen.begin(), entryDataSeen.end(), compareFn);
/* Check that the EntryData objects are contiguous. */
bool dataOffsetError = false;
EntryDataOffset expectedNextOffset = getFirstEntryDataOffset(bucket);
for (unsigned int i = 0; i < entryDataSeen.size(); i++) {
if (entryDataSeen[i].first != expectedNextOffset) {
/* The current entry does not start where expected. */
dataOffsetError = true;
break;
}
/* The next entry should start right after the current entry. */
expectedNextOffset += entryDataSeen[i].second + sizeof(EntryData);
}
/* the last EntryData should have ended at the very end of the
* bucket. */
if (expectedNextOffset != kBucketDataSize) {
dataOffsetError = true;
}
/* Throw an assert if something is wrong. */
if (headerOffsetError || dataOffsetError ||
totalSize != bucket->totalDataSize || nEntries != bucket->numEntries) {
/* Copy the bucket locally for easier debugging in case the slab is
* not in the core dump file. */
Bucket bucketCopy;
memcpy(&bucketCopy, bucket, sizeof(Bucket));
XDCHECK(false);
}
}