Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access only blocks to related to render #575

Merged
merged 1 commit into from Oct 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.md
Expand Up @@ -20,6 +20,8 @@ To be released.

### Added interfaces

- Added `BlockChain<T>.LongCount()` method. [[#575]]

### Behavioral changes

- Improved performance of `StoreExtension.LookupStateReference<T>()` method.
Expand All @@ -32,6 +34,8 @@ To be released.
already received when blockchain is empty. [[#550], [#562]]
- Fixed a bug that `Swarm<T>` had thrown `SocketException` with a message
`Operation on non-blocking socket would block`. [[#405], [#485]]
- Fixed a bug that accessed all blocks from the genesis block when a swap
occurred. [[#575]]

[#405]: https://github.com/planetarium/libplanet/issues/405
[#447]: https://github.com/planetarium/libplanet/issues/447
Expand All @@ -47,6 +51,7 @@ To be released.
[#563]: https://github.com/planetarium/libplanet/pull/563
[#209]: https://github.com/planetarium/libplanet/issues/209
[#561]: https://github.com/planetarium/libplanet/pull/561
[#575]: https://github.com/planetarium/libplanet/pull/575


Version 0.6.0
Expand Down
86 changes: 56 additions & 30 deletions Libplanet/Blockchain/BlockChain.cs
Expand Up @@ -114,30 +114,7 @@ public Block<T> Tip
/// All <see cref="Block{T}.Hash"/>es in the current index. The genesis block's hash goes
/// first, and the tip goes last.
/// </summary>
public IEnumerable<HashDigest<SHA256>> BlockHashes
{
get
{
try
{
_rwlock.EnterUpgradeableReadLock();

IEnumerable<HashDigest<SHA256>> indices = Store.IterateIndexes(Id);

// NOTE: The reason why this does not simply return indices, but iterates over
// indices and yields hashes step by step instead, is that we need to ensure
// the read lock held until the whole iteration completes.
foreach (HashDigest<SHA256> hash in indices)
{
yield return hash;
}
}
finally
{
_rwlock.ExitUpgradeableReadLock();
}
}
}
public IEnumerable<HashDigest<SHA256>> BlockHashes => IterateBlockHashes();

/// <inheritdoc/>
int IReadOnlyCollection<Block<T>>.Count =>
Expand Down Expand Up @@ -171,6 +148,14 @@ public IEnumerable<HashDigest<SHA256>> BlockHashes
}
}

/// <summary>
/// Returns a <see cref="long"/> integer that represents the number of elements in the
/// <see cref="BlockChain{T}"/>.
/// </summary>
/// <returns>A number that represents how many elements in the <see cref="BlockChain{T}"/>.
/// </returns>
public long LongCount() => Store.CountIndex(Id);

public void Validate(
IReadOnlyList<Block<T>> blocks,
DateTimeOffset currentTime
Expand Down Expand Up @@ -956,7 +941,7 @@ internal void Swap(BlockChain<T> other, bool render)
if (render && !(Tip is null || other.Tip is null))
{
long shorterHeight =
Math.Min(this.LongCount(), other.LongCount()) - 1;
Math.Min(LongCount(), other.LongCount()) - 1;
for (
Block<T> t = this[shorterHeight], o = other[shorterHeight];
t.PreviousHash is HashDigest<SHA256> tp &&
Expand Down Expand Up @@ -1030,11 +1015,12 @@ internal void Swap(BlockChain<T> other, bool render)
if (render)
{
// Render actions that had been behind.
IEnumerable<Block<T>> blocksToRender =
topmostCommon is Block<T> branchPoint
? this.SkipWhile(b => b.Index <= branchPoint.Index)
: this;
foreach (Block<T> b in blocksToRender)
long startToRenderIndex = topmostCommon is Block<T> branchPoint
? branchPoint.Index + 1
: 0;

// FIXME: We should consider the case where block count is larger than int.MaxSize.
foreach (Block<T> b in IterateBlocks(offset: (int)startToRenderIndex))
{
List<ActionEvaluation> evaluations = b.EvaluateActionsPerTx(a =>
GetState(a, b.PreviousHash).GetValueOrDefault(a))
Expand Down Expand Up @@ -1106,6 +1092,46 @@ bool buildStateReferences
}
}

private IEnumerable<Block<T>> IterateBlocks(int offset = 0, int? limit = null)
{
_rwlock.EnterUpgradeableReadLock();

try
{
foreach (HashDigest<SHA256> hash in IterateBlockHashes(offset, limit))
{
yield return Blocks[hash];
}
}
finally
{
_rwlock.ExitUpgradeableReadLock();
}
}

private IEnumerable<HashDigest<SHA256>>
IterateBlockHashes(int offset = 0, int? limit = null)
{
_rwlock.EnterUpgradeableReadLock();

try
{
IEnumerable<HashDigest<SHA256>> indices = Store.IterateIndexes(Id, offset, limit);

// NOTE: The reason why this does not simply return indices, but iterates over
// indices and yields hashes step by step instead, is that we need to ensure
// the read lock held until the whole iteration completes.
foreach (HashDigest<SHA256> hash in indices)
{
yield return hash;
}
}
finally
{
_rwlock.ExitUpgradeableReadLock();
}
}

/// <summary>
/// Provides data for the <see cref="TipChanged"/> event.
/// </summary>
Expand Down