/// <summary> /// Try take element from cached queue. /// </summary> /// <param name="height">Height of block info needed</param> /// <param name="blockCacheEntity"></param> /// <param name="isCacheSizeLimited">Use <see cref="CrossChainConstants.ChainCacheEntityCapacity"/> as cache count threshold if true.</param> /// <returns></returns> public bool TryTake(long height, out IBlockCacheEntity blockCacheEntity, bool isCacheSizeLimited) { // clear outdated data if (!_cache.TryGetValue(height, out blockCacheEntity)) { return(false); } var lastQueuedHeight = _targetHeight - 1; return(!isCacheSizeLimited || lastQueuedHeight >= height + CrossChainConstants.DefaultBlockCacheEntityCount); }
/// <summary> /// Cache block info lately removed. /// Dequeue one element if the cached count reaches <see cref="CrossChainConstants.ChainCacheEntityCapacity"/> /// </summary> /// <param name="blockCacheEntity"></param> private bool TryDequeue(out IBlockCacheEntity blockCacheEntity) { var res = BlockCacheEntities.TryTake(out blockCacheEntity, CrossChainConstants.WaitingIntervalInMillisecond); if (res) { DequeuedBlockCacheEntities.Add(blockCacheEntity); } return(res); }
public bool TryAdd(IBlockCacheEntity blockCacheEntity) { if (BlockCacheEntities.Count >= CrossChainConstants.ChainCacheEntityCapacity) { return(false); } // thread unsafe in some extreme cases, but it can be covered with caching mechanism. if (blockCacheEntity.Height != TargetChainHeight()) { return(false); } var res = BlockCacheEntities.TryAdd(blockCacheEntity); return(res); }
public bool TryAdd(IBlockCacheEntity blockCacheEntity) { if (blockCacheEntity.Height != TargetChainHeight()) { return(false); } var res = ValidateBlockCacheEntity(blockCacheEntity) && _cache.TryAdd(blockCacheEntity.Height, blockCacheEntity); if (res) { _targetHeight = blockCacheEntity.Height + 1; } return(res); }
public bool TryAddBlockCacheEntity(IBlockCacheEntity blockCacheEntity) { if (blockCacheEntity == null) { throw new ArgumentNullException(nameof(blockCacheEntity)); } if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(blockCacheEntity.ChainId, out var chainCacheEntity)) { return(false); } var res = chainCacheEntity.TryAdd(blockCacheEntity); Logger.LogTrace( $"Cached height {blockCacheEntity.Height} from chain {ChainHelper.ConvertChainIdToBase58(blockCacheEntity.ChainId)}, {res}"); return(res); }
/// <summary> /// Try take element from cached queue. /// Make sure that more than <see cref="CrossChainConstants.MinimalBlockCacheEntityCount"/> block cache entities are left in <see cref="BlockCacheEntities"/>. /// </summary> /// <param name="height">Height of block info needed</param> /// <param name="blockCacheEntity"></param> /// <param name="isCacheSizeLimited">Use <see cref="CrossChainConstants.ChainCacheEntityCapacity"/> as cache count threshold if true.</param> /// <returns></returns> public bool TryTake(long height, out IBlockCacheEntity blockCacheEntity, bool isCacheSizeLimited) { // clear outdated data var cachedInQueue = DequeueBlockCacheEntitiesBeforeHeight(height); // isCacheSizeLimited means minimal caching size limit, so that most nodes have this block. var lastQueuedHeight = BlockCacheEntities.LastOrDefault()?.Height ?? 0; if (cachedInQueue && !(isCacheSizeLimited && lastQueuedHeight < height + CrossChainConstants.MinimalBlockCacheEntityCount)) { return(TryDequeue(out blockCacheEntity)); } blockCacheEntity = GetLastDequeuedBlockCacheEntity(height); if (blockCacheEntity != null) { return(!isCacheSizeLimited || BlockCacheEntities.Count + DequeuedBlockCacheEntities.Count(ci => ci.Height >= height) >= CrossChainConstants.MinimalBlockCacheEntityCount); } return(false); }
private bool ValidateBlockCacheEntity(IBlockCacheEntity blockCacheEntity) { return(blockCacheEntity.Height >= AElfConstants.GenesisBlockHeight && blockCacheEntity.ChainId == _chainId && blockCacheEntity.TransactionStatusMerkleTreeRoot != null); }