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

Boost PreloadAsync() #420

Merged
merged 2 commits into from Aug 27, 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
8 changes: 8 additions & 0 deletions CHANGES.md
Expand Up @@ -8,6 +8,13 @@ To be released.

### Backward-incompatible interface changes

- `IStore.StoreStateReference<T>(string, IImmutableSet<Address>, Block<T>)`
method became replaced by
`StoreStateReference(string, IImmutableSet<Address>, HashDigest<SHA256>, long)`
method so that it takes hash and index of a block instead of an entire
block. [[#420]]
- Added `IStore.ForkBlockIndexes()` method. [[#420]]

### Added interfaces

### Behavioral changes
Expand All @@ -17,6 +24,7 @@ To be released.
- Fixed a bug that `Swarm<T>` hadn't released its TURN releated resources on
`Swarm<T>.StopAsync()`. [[#450]]

[#420]: https://github.com/planetarium/libplanet/pull/420
[#450]: https://github.com/planetarium/libplanet/pull/450


Expand Down
3 changes: 2 additions & 1 deletion Libplanet.Tests/Blockchain/BlockChainTest.cs
Expand Up @@ -1392,7 +1392,8 @@ void BuildIndex(Guid id, Block<DumbAction> block)
store.StoreStateReference(
chainId.ToString(),
dirty.Keys.ToImmutableHashSet(),
b
b.Hash,
b.Index
);
BuildIndex(chainId, b);
}
Expand Down
14 changes: 12 additions & 2 deletions Libplanet.Tests/Store/StoreExtensionTest.cs
Expand Up @@ -47,7 +47,12 @@ public void LookupStateReference(StoreFixture fx)
Assert.Null(fx.Store.LookupStateReference(fx.StoreNamespace, address, block5));
Assert.Null(fx.Store.LookupStateReference(fx.StoreNamespace, address, block6));

fx.Store.StoreStateReference(fx.StoreNamespace, tx4.UpdatedAddresses, block4);
fx.Store.StoreStateReference(
fx.StoreNamespace,
tx4.UpdatedAddresses,
block4.Hash,
block4.Index
);
Assert.Null(fx.Store.LookupStateReference(fx.StoreNamespace, address, fx.Block3));
Assert.Equal(
Tuple.Create(block4.Hash, block4.Index),
Expand All @@ -62,7 +67,12 @@ public void LookupStateReference(StoreFixture fx)
fx.Store.LookupStateReference(fx.StoreNamespace, address, block6)
);

fx.Store.StoreStateReference(fx.StoreNamespace, tx5.UpdatedAddresses, block5);
fx.Store.StoreStateReference(
fx.StoreNamespace,
tx5.UpdatedAddresses,
block5.Hash,
block5.Index
);
Assert.Null(fx.Store.LookupStateReference(
fx.StoreNamespace, address, fx.Block3));
Assert.Equal(
Expand Down
38 changes: 30 additions & 8 deletions Libplanet.Tests/Store/StoreTest.cs
Expand Up @@ -51,7 +51,8 @@ public void DeleteNamespace()
Fx.Store.StoreStateReference(
Fx.StoreNamespace,
addresses.Take(3).ToImmutableHashSet(),
block1
block1.Hash,
block1.Index
);
Fx.Store.IncreaseTxNonce(Fx.StoreNamespace, Fx.Transaction1.Signer);

Expand Down Expand Up @@ -87,7 +88,8 @@ public void ListAddresses()
Fx.Store.StoreStateReference(
Fx.StoreNamespace,
addresses.Take(3).ToImmutableHashSet(),
Fx.Block1
Fx.Block1.Hash,
Fx.Block1.Index
);
Assert.Equal(
addresses.Take(3).ToImmutableHashSet(),
Expand All @@ -96,7 +98,8 @@ public void ListAddresses()
Fx.Store.StoreStateReference(
Fx.StoreNamespace,
addresses.Skip(2).Take(3).ToImmutableHashSet(),
Fx.Block2
Fx.Block2.Hash,
Fx.Block2.Index
);
Assert.Equal(
addresses.Take(5).ToImmutableHashSet(),
Expand All @@ -105,7 +108,8 @@ public void ListAddresses()
Fx.Store.StoreStateReference(
Fx.StoreNamespace,
addresses.Skip(5).Take(3).ToImmutableHashSet(),
Fx.Block3
Fx.Block3.Hash,
Fx.Block3.Index
);
Assert.Equal(
addresses.ToImmutableHashSet(),
Expand Down Expand Up @@ -343,13 +347,23 @@ public void IterateStateReferences()

Assert.Empty(this.Fx.Store.IterateStateReferences(this.Fx.StoreNamespace, address));

Fx.Store.StoreStateReference(Fx.StoreNamespace, tx4.UpdatedAddresses, block4);
Fx.Store.StoreStateReference(
Fx.StoreNamespace,
tx4.UpdatedAddresses,
block4.Hash,
block4.Index
);
Assert.Equal(
new[] { Tuple.Create(block4.Hash, block4.Index) },
this.Fx.Store.IterateStateReferences(this.Fx.StoreNamespace, address)
);

Fx.Store.StoreStateReference(Fx.StoreNamespace, tx5.UpdatedAddresses, block5);
Fx.Store.StoreStateReference(
Fx.StoreNamespace,
tx5.UpdatedAddresses,
block5.Hash,
block5.Index
);
Assert.Equal(
new[]
{
Expand Down Expand Up @@ -392,15 +406,23 @@ public void ForkStateReferences(int branchPointIndex)
{
updatedAddresses = new HashSet<Address> { address1 };
Fx.Store.StoreStateReference(
Fx.StoreNamespace, updatedAddresses.ToImmutableHashSet(), block);
Fx.StoreNamespace,
updatedAddresses.ToImmutableHashSet(),
block.Hash,
block.Index
);
}

var txs2 = new[] { tx2 };
blocks.Add(TestUtils.MineNext(blocks[2], txs2));

updatedAddresses = new HashSet<Address> { address2 };
Fx.Store.StoreStateReference(
Fx.StoreNamespace, updatedAddresses.ToImmutableHashSet(), blocks[3]);
Fx.StoreNamespace,
updatedAddresses.ToImmutableHashSet(),
blocks[3].Hash,
blocks[3].Index
);

var branchPoint = blocks[branchPointIndex];
var addressesToStrip = new[] { address1, address2 }.ToImmutableHashSet();
Expand Down
19 changes: 14 additions & 5 deletions Libplanet.Tests/Store/StoreTracker.cs
Expand Up @@ -176,15 +176,15 @@ AddressStateMap states
return _store.IterateStateReferences(@namespace, address);
}

public void StoreStateReference<T>(
public void StoreStateReference(
string @namespace,
IImmutableSet<Address> addresses,
Block<T> block)
where T : IAction, new()
HashDigest<SHA256> blockHash,
long blockIndex)
{
// FIXME: Log arguments properly (including @namespace).
_logs.Add((nameof(StoreStateReference), block.Hash, null));
_store.StoreStateReference(@namespace, addresses, block);
_logs.Add((nameof(StoreStateReference), blockHash, null));
_store.StoreStateReference(@namespace, addresses, blockHash, blockIndex);
}

public void ForkStateReferences<T>(
Expand All @@ -200,6 +200,15 @@ AddressStateMap states
sourceNamespace, destinationNamespace, branchPoint, addressesToStrip);
}

public void ForkBlockIndexes(
string sourceNamespace,
string destinationNamespace,
HashDigest<SHA256> branchPoint)
{
_logs.Add((nameof(ForkBlockIndexes), null, null));
_store.ForkBlockIndexes(sourceNamespace, destinationNamespace, branchPoint);
}

public IEnumerable<KeyValuePair<Address, long>> ListTxNonces(string @namespace)
{
_logs.Add((nameof(ListTxNonces), @namespace, null));
Expand Down
16 changes: 7 additions & 9 deletions Libplanet/Blockchain/BlockChain.cs
Expand Up @@ -815,15 +815,8 @@ internal BlockChain<T> Fork(HashDigest<SHA256> point)
try
{
_rwlock.EnterReadLock();
foreach (var index in Store.IterateIndex(id))
{
Store.AppendIndex(forkedId, index);
if (index.Equals(point))
{
break;
}
}

Store.ForkBlockIndexes(id, forkedId, point);
Block<T> pointBlock = Blocks[point];

var addressesToStrip = new HashSet<Address>();
Expand Down Expand Up @@ -1080,7 +1073,12 @@ bool buildStateReferences

if (buildStateReferences)
{
Store.StoreStateReference(Id.ToString(), updatedAddresses, block);
Store.StoreStateReference(
Id.ToString(),
updatedAddresses,
block.Hash,
block.Index
);
}
}
}
Expand Down
5 changes: 0 additions & 5 deletions Libplanet/Net/StateReferenceDownloadState.cs
Expand Up @@ -17,11 +17,6 @@ public class StateReferenceDownloadState : PreloadState
/// </summary>
public int ReceivedStateReferenceCount { get; internal set; }

/// <summary>
/// The address of the state references just received.
/// </summary>
public Address ReceivedAddress { get; internal set; }

/// <inheritdoc />
public override int CurrentPhase => 2;
}
Expand Down
22 changes: 19 additions & 3 deletions Libplanet/Net/Swarm.cs
Expand Up @@ -1042,21 +1042,37 @@ bool render

int count = 0, totalCount = recentStates.StateReferences.Count;
_logger.Debug("Starts to store state refs received from {0}.", peer);

var d = new Dictionary<HashDigest<SHA256>, ISet<Address>>();
foreach (var pair in recentStates.StateReferences)
{
cancellationToken.ThrowIfCancellationRequested();
IImmutableSet<Address> address = ImmutableHashSet.Create(pair.Key);
foreach (HashDigest<SHA256> bHash in pair.Value)
{
Block<T> block = store.GetBlock<T>(bHash);
store.StoreStateReference(ns, address, block);
if (!d.ContainsKey(bHash))
{
d[bHash] = new HashSet<Address>();
}

d[bHash].UnionWith(address);
}
}

totalCount = d.Count;
foreach (KeyValuePair<HashDigest<SHA256>, ISet<Address>> pair in d)
{
HashDigest<SHA256> hash = pair.Key;
IImmutableSet<Address> addresses = pair.Value.ToImmutableHashSet();
if (store.GetBlockIndex(hash) is long index)
{
store.StoreStateReference(ns, addresses, hash, index);
}

progress?.Report(new StateReferenceDownloadState()
{
TotalStateReferenceCount = totalCount,
ReceivedStateReferenceCount = ++count,
ReceivedAddress = pair.Key,
});
}

Expand Down
13 changes: 9 additions & 4 deletions Libplanet/Store/BaseStore.cs
Expand Up @@ -38,6 +38,12 @@ long index
HashDigest<SHA256> hash
);

/// <inheritdoc />
public abstract void ForkBlockIndexes(
string sourceNamespace,
string destinationNamespace,
HashDigest<SHA256> branchPoint);

/// <inheritdoc />
public abstract IEnumerable<Address> ListAddresses(string @namespace);

Expand Down Expand Up @@ -119,12 +125,11 @@ AddressStateMap states
public abstract IEnumerable<Tuple<HashDigest<SHA256>, long>> IterateStateReferences(
string @namespace, Address address);

/// <inheritdoc />
public abstract void StoreStateReference<T>(
public abstract void StoreStateReference(
string @namespace,
IImmutableSet<Address> addresses,
Block<T> block)
where T : IAction, new();
HashDigest<SHA256> hashDigest,
long index);

/// <inheritdoc />
public abstract void ForkStateReferences<T>(
Expand Down
46 changes: 34 additions & 12 deletions Libplanet/Store/IStore.cs
Expand Up @@ -53,6 +53,26 @@ public interface IStore

bool DeleteIndex(string @namespace, HashDigest<SHA256> hash);

/// <summary>
/// Forks block indexes from
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the term “block indexes” mean a sequence (chain) of block hashes and its index numbers? Or does it include state references? If it's latter the plural term seems natural for me as well, but if it's former I believe the singular term (i.e., “block index”) would listen more natural IMHO (as like the way other related methods are named, e.g., AppendIndex, DeleteIndex, IterateIndex).

Copy link
Member Author

@longfin longfin Aug 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's former. but I've confused about that because….

  • AppendIndex() and DeleteIndex() take only one argument.
  • Other iteration methods use plural form. (e.g. IterateBlockHashes(), IterateStateReferences())

So, how about keep ForkIndexes() in this PR and rename IterateIndex() to IterateIndexes() in other PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO in the case of this a singular noun “index” is more natural than a plural noun “indexes”/“indices,” in the same manner we say “a set of blocks” instead of “sets of blocks” to mean ISet[Block] in verbal language.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this terminology once more, and it turns out the plural term has its own advantage, and I agree your suggestion to rename these method names to use the plural term “indexes” instead of the singular “index.” Some reasons:

  • Although relational databases tend to say “an index” for values in a column, we also say “indices” in books.
  • We already name a block's height by Block.Index, so it's natural to say a collection of Block.Indexes as the plural “indexes.”

/// <paramref name="sourceNamespace"/> to
/// <paramref name="destinationNamespace"/>.
/// </summary>
/// <param name="sourceNamespace">The namespace of block indexes to
/// fork.</param>
/// <param name="destinationNamespace">The namespace of destination
/// block indexes.</param>
/// <param name="branchPoint">The branch point <see cref="Block{T}"/>
/// to fork.</param>
/// <exception cref="NamespaceNotFoundException">Thrown when the given
/// <paramref name="sourceNamespace"/> does not exist.</exception>
/// <seealso cref="IterateIndex(string, int, int?)"/>
/// <seealso cref="AppendIndex(string, HashDigest{SHA256})"/>
void ForkBlockIndexes(
string sourceNamespace,
string destinationNamespace,
HashDigest<SHA256> branchPoint);

/// <summary>
/// Deletes an index, tx nonces, and state references in the given
/// <paramref name="namespace"/>.
Expand Down Expand Up @@ -175,6 +195,7 @@ void PutBlock<T>(Block<T> block)
AddressStateMap states
);

#pragma warning disable MEN002
/// <summary>
/// Gets pairs of a state reference and a corresponding <see cref="Block{T}.Index"/> of
/// the requested <paramref name="address"/> in the specified <paramref name="namespace"/>.
Expand All @@ -184,7 +205,8 @@ AddressStateMap states
/// <returns><em>Ordered</em> pairs of a state reference and a corresponding
/// <see cref="Block{T}.Index"/>. The highest index (i.e., the closest to the tip) goes
/// first and the lowest index (i.e., the closest to the genesis) goes last.</returns>
/// <seealso cref="StoreStateReference{T}(string, IImmutableSet{Address}, Block{T})"/>
/// <seealso cref="StoreStateReference(string, IImmutableSet{Address}, HashDigest{SHA256}, long)"/>
#pragma warning restore MEN002 // Line is too long
IEnumerable<Tuple<HashDigest<SHA256>, long>> IterateStateReferences(
string @namespace,
Address address);
Expand All @@ -193,25 +215,24 @@ AddressStateMap states
/// Stores a state reference, which is a <see cref="Block{T}.Hash"/>
/// that has the state of the <see cref="Address"/> for each updated
/// <see cref="Address"/>es by the <see cref="Transaction{T}"/>s in the
/// <paramref name="block"/>.</summary>
/// <see cref="Block{T}" />.</summary>
/// <param name="namespace">The namespace to store a state reference.
/// </param>
/// <param name="addresses">The <see cref="Address"/>es to store state
/// reference.</param>
/// <param name="block">The <see cref="Block{T}"/> which has the state
/// <param name="blockHash">The <see cref="Block{T}.Hash"/> which has the state
/// of the <see cref="Address"/>.</param>
longfin marked this conversation as resolved.
Show resolved Hide resolved
/// <typeparam name="T">An <see cref="IAction"/> class used with
/// <paramref name="block"/>.</typeparam>
/// <remarks>State reference must be stored in the same order as the blocks. For now,
/// it is assumed that this is only called by
/// <see cref="BlockChain{T}.Append(Block{T})"/> method.</remarks>
/// <param name="blockIndex">The <see cref="Block{T}.Index"/> which has the state
/// of the <see cref="Address"/>. This must refer to the same block
/// that <paramref name="blockHash"/> refers to.</param>
/// <seealso cref="IterateStateReferences(string, Address)"/>
void StoreStateReference<T>(
void StoreStateReference(
string @namespace,
IImmutableSet<Address> addresses,
Block<T> block)
where T : IAction, new();
HashDigest<SHA256> blockHash,
long blockIndex);

#pragma warning disable MEN002
/// <summary>
/// Forks state references, which are <see cref="Block{T}.Hash"/>es that
/// have the state of the <see cref="Address"/>es, from
Expand All @@ -236,7 +257,8 @@ AddressStateMap states
/// <exception cref="NamespaceNotFoundException">Thrown when the given
/// <paramref name="sourceNamespace"/> does not exist.</exception>
/// <seealso cref="IterateStateReferences(string, Address)"/>
/// <seealso cref="StoreStateReference{T}(string, IImmutableSet{Address}, Block{T})"/>
/// <seealso cref="StoreStateReference(string, IImmutableSet{Address}, HashDigest{SHA256}, long)"/>
#pragma warning restore MEN002
void ForkStateReferences<T>(
string sourceNamespace,
string destinationNamespace,
Expand Down