void CompactionCore()
{
var token = _compactionCts.Token;
var usage = new Dictionary<uint, ulong>();
var finishedUsageStats = true;
uint maxAccessRate = 0;
foreach (var cacheValue in _cache.Values)
{
if (token.IsCancellationRequested)
{
finishedUsageStats = false;
break;
}
ulong accessRateRunningTotal;
usage.TryGetValue(cacheValue.FileId, out accessRateRunningTotal);
uint accessRate = cacheValue.AccessRate;
if (maxAccessRate < accessRate) maxAccessRate = accessRate;
accessRateRunningTotal += accessRate;
usage[cacheValue.FileId] = accessRateRunningTotal;
}
var usageList = new List<RateFilePair>();
var fileIdsToRemove = new List<uint>();
foreach (var fileInfo in _fileInfos)
{
if (fileInfo.Value.FileType != DiskChunkFileType.PureValues) continue;
if (fileInfo.Key == _cacheValueFileId) continue;
ulong accessRate;
if (!usage.TryGetValue(fileInfo.Key, out accessRate) && finishedUsageStats)
{
fileIdsToRemove.Add(fileInfo.Key);
continue;
}
usageList.Add(new RateFilePair(accessRate, fileInfo.Key));
}
usageList.Sort((a, b) => a.AccessRate > b.AccessRate ? -1 : a.AccessRate < b.AccessRate ? 1 : 0);
while (usageList.Count >= _maxValueFileCount)
{
var fileId = usageList.Last().FileId;
if (usageList.Count == _maxValueFileCount)
PreserveJustMostOftenUsed(fileId);
else
ClearFileFromCache(fileId);
fileIdsToRemove.Add(fileId);
usageList.RemoveAt(usageList.Count - 1);
}
FlushCurrentValueFile();
StoreHashIndex();
foreach (var fileid in fileIdsToRemove)
{
_fileCollection.GetFile(fileid).Remove();
_fileInfos.TryRemove(fileid);
}
}