/// <summary> /// Try Take element from cached queue. /// </summary> /// <param name="height">Height of block info needed</param> /// <param name="blockInfo"></param> /// <param name="isCacheSizeLimited">Use <see cref="_cachedBoundedCapacity"/> as cache count threshold if true.</param> /// <returns></returns> public bool TryTake(long height, out IBlockInfo blockInfo, bool isCacheSizeLimited) { // clear outdated data var cachedInQueue = CacheBlockInfoBeforeHeight(height); // isCacheSizeLimited means minimal caching size limit, so that most nodes have this block. var lastQueuedHeight = ToBeIndexedBlockInfoQueue.LastOrDefault()?.Height ?? 0; if (cachedInQueue && !(isCacheSizeLimited && lastQueuedHeight < height + CrossChainConstants.MinimalBlockInfoCacheThreshold)) { var res = ToBeIndexedBlockInfoQueue.TryTake(out blockInfo, CrossChainConstants.WaitingIntervalInMillisecond); if (res) { CacheBlockInfo(blockInfo); } return(res); } blockInfo = LastBlockInfoInCache(height); if (blockInfo != null) { return(!isCacheSizeLimited || ToBeIndexedBlockInfoQueue.Count + CachedIndexedBlockInfoQueue.Count(ci => ci.Height >= height) >= CrossChainConstants.MinimalBlockInfoCacheThreshold); } return(false); }
/// <summary> /// Cache outdated data. The block with height lower than <paramref name="height"/> is outdated. /// </summary> /// <param name="height"></param> private bool CacheBlockInfoBeforeHeight(long height) { while (true) { var blockInfo = ToBeIndexedBlockInfoQueue.FirstOrDefault(); if (blockInfo == null || blockInfo.Height > height) { return(false); } if (blockInfo.Height == height) { return(true); } var res = ToBeIndexedBlockInfoQueue.TryTake(out blockInfo, CrossChainConstants.WaitingIntervalInMillisecond); if (res) { CacheBlockInfo(blockInfo); } } }